D
David Mathog
This one is driving me slightly batty. The code in question is
buried deep in somebody else's massive package but it boils down to
this, two pointers are declared, the first is:
char **resname
which is part of the "atoms" structure that is passed into the function
from the outside. I have not yet found where it is allocated but I'm
reasonably sure from other chunks of this code that it was by:
atoms->resname=malloc(sizeof(char**)*SOMENUMBER);
Within my function these are found:
char **pnew_res_names;
pnew_res_names=malloc(sizeof(char*)*10);
/* char ***, pointers to pointers to pointers to the name strings */
(void) fprintf(stderr,"0e: %8x\n",(void *)atoms->resname);
/* char **, pointers to pointers to the name strings */
(void) fprintf(stderr,"0f: %8x\n",(void *)(atoms->resname[0]));
(void) fprintf(stderr,"1f: %8x\n",(void *)(atoms->resname[1]));
(void) fprintf(stderr,"2f: %8x\n",(void *)(atoms->resname[2]));
/* char *, pointers to the first characters in the name strings */
(void) fprintf(stderr,"0g: %8x\n",(void *) *(atoms->resname[0]));
(void) fprintf(stderr,"1g: %8x\n",(void *) *(atoms->resname[1]));
(void) fprintf(stderr,"2g: %8x\n",(void *) *(atoms->resname[2]));
atoms->resname= (char ***) &pnew_res_names;
/* the explict cast doesn't seem to make any difference */
/* char **, pointers to pointers to the name strings */
(void) fprintf(stderr,"-1a: %8x\n",(void *) pnew_res_names);
/* char *, pointers to the first characters in the name strings */
(void) fprintf(stderr,"0a: %8x\n",(void *)pnew_res_names[0]);
(void) fprintf(stderr,"1a: %8x\n",(void *)pnew_res_names[1]);
(void) fprintf(stderr,"2a: %8x\n",(void *)pnew_res_names[2]);
/* char **, pointers to pointers to the name strings */
(void) fprintf(stderr,"0b: %8x\n",(void *)(atoms->resname[0]));
(void) fprintf(stderr,"1b: %8x\n",(void *)(atoms->resname[1]));
(void) fprintf(stderr,"2b: %8x\n",(void *)(atoms->resname[2]));
/* char *, pointers to the first characters in the name strings */
(void) fprintf(stderr,"0c: %8x\n",(void *) *(atoms->resname[0]));
(void) fprintf(stderr,"1c: %8x\n",(void *) *(atoms->resname[1]));
(void) fprintf(stderr,"2c: %8x\n",(void *) *(atoms->resname[2]));
When this code runs it emits this:
0e: 804c110 #so the original atoms->resname can be accessed by
0f: 804a6e8 #indices
1f: 804a750
2f: 804a75c
0g: 804b6e8
1g: 804b888
2g: 804b8b8
-1a: 80e98e0 #location of pnew_res_names
0a: 804b6e8 #first points to first string
1a: 804b6f8 #second points to second string
2a: 804b708 #third points to third string
0b: 80e98e0 #atoms->resname[0] points to first spot in pnew_res_names
1b: 0 #second is broken, no pointer to 2nd string, but see 1a
2b: 0 #third is broken, no pointer to 3rd string, but see 2a
0c: 804b6e8 #correctly points to first string
segfaults when it tries to reference address 0.
In other words, the chunk of memory that was originally allocated
and passed in as atoms->resname can be accessed by indices
properly. The newly allocated region can also be accessed
when referenced from pnew_res_names. However, it cannot be
accessed via indices through atoms->resname after that is set
to point to the memory block. The first value works
properly, but the second and subsequent ones do not.
All (reasonable) accesses to atoms->resname work before the memory
block is reassigned. All (reasonable) accesses to pnew_res_names
work before and after the memory block is reassigned. But mixed
pointer/index accesses to the data in pnew_res_names does not work
once it is linked to atoms->resname.
Why? Or more specifically, is there some magical cast that can
be used instead of (char ***) to make this work?
Thanks,
David Mathog
ude TOD hcetlac TA gohtam
buried deep in somebody else's massive package but it boils down to
this, two pointers are declared, the first is:
char **resname
which is part of the "atoms" structure that is passed into the function
from the outside. I have not yet found where it is allocated but I'm
reasonably sure from other chunks of this code that it was by:
atoms->resname=malloc(sizeof(char**)*SOMENUMBER);
Within my function these are found:
char **pnew_res_names;
pnew_res_names=malloc(sizeof(char*)*10);
/* char ***, pointers to pointers to pointers to the name strings */
(void) fprintf(stderr,"0e: %8x\n",(void *)atoms->resname);
/* char **, pointers to pointers to the name strings */
(void) fprintf(stderr,"0f: %8x\n",(void *)(atoms->resname[0]));
(void) fprintf(stderr,"1f: %8x\n",(void *)(atoms->resname[1]));
(void) fprintf(stderr,"2f: %8x\n",(void *)(atoms->resname[2]));
/* char *, pointers to the first characters in the name strings */
(void) fprintf(stderr,"0g: %8x\n",(void *) *(atoms->resname[0]));
(void) fprintf(stderr,"1g: %8x\n",(void *) *(atoms->resname[1]));
(void) fprintf(stderr,"2g: %8x\n",(void *) *(atoms->resname[2]));
atoms->resname= (char ***) &pnew_res_names;
/* the explict cast doesn't seem to make any difference */
/* char **, pointers to pointers to the name strings */
(void) fprintf(stderr,"-1a: %8x\n",(void *) pnew_res_names);
/* char *, pointers to the first characters in the name strings */
(void) fprintf(stderr,"0a: %8x\n",(void *)pnew_res_names[0]);
(void) fprintf(stderr,"1a: %8x\n",(void *)pnew_res_names[1]);
(void) fprintf(stderr,"2a: %8x\n",(void *)pnew_res_names[2]);
/* char **, pointers to pointers to the name strings */
(void) fprintf(stderr,"0b: %8x\n",(void *)(atoms->resname[0]));
(void) fprintf(stderr,"1b: %8x\n",(void *)(atoms->resname[1]));
(void) fprintf(stderr,"2b: %8x\n",(void *)(atoms->resname[2]));
/* char *, pointers to the first characters in the name strings */
(void) fprintf(stderr,"0c: %8x\n",(void *) *(atoms->resname[0]));
(void) fprintf(stderr,"1c: %8x\n",(void *) *(atoms->resname[1]));
(void) fprintf(stderr,"2c: %8x\n",(void *) *(atoms->resname[2]));
When this code runs it emits this:
0e: 804c110 #so the original atoms->resname can be accessed by
0f: 804a6e8 #indices
1f: 804a750
2f: 804a75c
0g: 804b6e8
1g: 804b888
2g: 804b8b8
-1a: 80e98e0 #location of pnew_res_names
0a: 804b6e8 #first points to first string
1a: 804b6f8 #second points to second string
2a: 804b708 #third points to third string
0b: 80e98e0 #atoms->resname[0] points to first spot in pnew_res_names
1b: 0 #second is broken, no pointer to 2nd string, but see 1a
2b: 0 #third is broken, no pointer to 3rd string, but see 2a
0c: 804b6e8 #correctly points to first string
segfaults when it tries to reference address 0.
In other words, the chunk of memory that was originally allocated
and passed in as atoms->resname can be accessed by indices
properly. The newly allocated region can also be accessed
when referenced from pnew_res_names. However, it cannot be
accessed via indices through atoms->resname after that is set
to point to the memory block. The first value works
properly, but the second and subsequent ones do not.
All (reasonable) accesses to atoms->resname work before the memory
block is reassigned. All (reasonable) accesses to pnew_res_names
work before and after the memory block is reassigned. But mixed
pointer/index accesses to the data in pnew_res_names does not work
once it is linked to atoms->resname.
Why? Or more specifically, is there some magical cast that can
be used instead of (char ***) to make this work?
Thanks,
David Mathog
ude TOD hcetlac TA gohtam