我的主要目的是将指向结构的指针传递给函数,该函数将分配内存并填充其所有值。返回后我会在屏幕上打印出来。
结构看起来像这样。
struct isolock{
char *name;
unsigned int state;};
typedef struct isolock lock;
请注意我无法更改此结构的声明。我的主要功能非常简单。
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函数假设为我的结构分配n + 1个内存块,其中n是存在的实际锁定数。而最后(第n + 1)个块将填充零。因此,当从main打印时,我可以检查这种情况,而不必担心我已分配的结构长度。
我的问题在于fillArray函数。
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
实际上这个LINE100会导致问题。它实际上替换了已填充的结构条目,即该行使dlock [0] - &gt; name填充0.而dlock [1]保持不变。
我的gdb日志显示如下内容。
所有这些都是在分配和填充值之后获取的日志。
(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
从注释1和注释2可以看出,strdup已经通过malloc返回已经分配的内存位置,即首先调用strdup已经返回了dlock的地址[2]。怎么会发生这种情况。因此,(* dlock + 2) - &gt; name = 0导致dlock [0] - &gt;名称填充为0。
要轻松解释这个问题, Malloc给了我三个地址。为了便于理解,可以说,{1000,1008,1010} 有两次我称之为strdup,已经返回{1010,1018}
这个1010和1018分别存储在锁[0]和锁[1]的char *名称中。
有人能告诉我,我在这段代码中做错了什么,或者是strdup这个问题(分配已经分配的内存块)
注意:当我将char * name更改为char name [20]而不是strdup时,我使用了strcpy并且它运行良好。
答案 0 :(得分:2)
错误的可能原因是您的分配:
*dlock = (isolock *)malloc((sizeof (*dlock)) * 3);
此处dlock
是指向指针的指针,因此sizeof(*dlock)
是指针的大小,与sizeof(struct isolock)
(或sizeof(**dlock)
)不同。