My main intention is to pass a pointer to a structure, to a function, which will allocate memory and fill all its values. After returning back i will print it on screen.
Structure looks like this.
struct isolock{
char *name;
unsigned int state;};
typedef struct isolock lock;
Please note i can not change declaration of this structure. My main function is very simple like this.
int main(){
int i = 0;
isolock *lock = NULL;
fillArray(&lock);
//print struct contents
for(i=0;(lock+i)->name;i++){
printf("name = %s status = %u \n", (lock+i)->name,(lock+i)->state);
}
}
fillArray function is suppose to allocate n + 1 memory blocks for my structure where n is the actual number of locks present. whereas last (n+1)th block will be filled with zero. So that while printing from main, i can just check for this condition, without need of worrying about length of structures which i have allocated.
My problem is in fillArray function.
static const char *array[] = {"SWMGMT_LOCK","OTHER_LOCK"};
void fillArray(isolock **dlock){
int i = 0;
if (*dlock == NULL){
*dlock = (isolock *)malloc((sizeof (*dlock)) * 3); //allocate space for holding 3 struct values
for(i=0;i<2;i++){
(*(dlock) + i)->name = strdup(array[i]);
(*(dlock) + i)->state = (unsigned int)(i+1);
}
(*(dlock) + i)->name = 0; //LINE100
(*(dlock) + i)->state = 0;
}
}
o/p:
name = status = 1
name = OTHER_FP_LOCK status = 2
Actually this LINE100 causes problem. It actually replaces already filled structure entry i.e., this line makes dlock[0]->name to be filled with 0. whereas dlock[1] remains unchanged.
My gdb log shows something like this.
All these are logs are taken after allocation and filling values.
(gdb) p (*(dlock)+0)
$10 = (isolock *) 0x804b008
(gdb) p (*(dlock)+1)
$11 = (isolock *) 0x804b010
(gdb) p (*(dlock)+2) <== Note here 1
$12 = (isolock *) 0x804b018
(gdb) p *(*(dlock)+0)
$13 = {name = 0x804b018 "SWMGMT_LOCK", state = 1} <== Note here 2
(gdb) p *(*(dlock)+1)
$14 = {name = 0x804b028 "OTHER_FP_LOCK", state = 2}
(gdb) n
33 (*(dlock) + i)->state = 0;
(gdb)
35 }
(gdb) p *(*(dlock)+2)
$15 = {name = 0x0, state = 0}
(gdb) p (*(dlock)+2)
$16 = (isolock *) 0x804b018
From note 1 and note 2 its very clear that, strdup has returned already allocated memory location by malloc i.e., first call to strdup has returned the address of dlock[2]. how could this happen. because of this, (*dlock+2)->name = 0 has caused dlock[0]->name to be filled with 0.
To easily explain this problem, Malloc has returned me three addresses. for easy understanding lets say, {1000,1008,1010} Two times i ve called strdup which has returned {1010,1018}
this 1010 and 1018 are stored in char *name of lock[0] and lock[1] respectively.
Can someone tell me, am i doing something wrong in this code or is this problem of strdup ( allocating a already allocated block of memory)
NOTE: When i have changed char *name to char name[20] and instead of strdup, i used strcpy and it worked perfectly.
A possible cause of the error is your allocation:
*dlock = (isolock *)malloc((sizeof (*dlock)) * 3);
Here dlock
is a pointer to a pointer, so sizeof(*dlock)
is the size of a pointer which is not the same as sizeof(struct isolock)
(or sizeof(**dlock)
).