-2

我的主要目的是将一个指向结构的指针传递给一个函数,该函数将分配内存并填充其所有值。回来后我会在屏幕上打印出来。

结构看起来像这样。

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]->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)->name = 0 导致 dlock[0]->name 被填充为 0。

为了方便解释这个问题,Malloc 给我回了三个地址。为了便于理解,可以说,{1000,1008,1010} 我调用了两次 strdup,它返回了 {1010,1018}

这 1010 和 1018 分别存储在 char *name of lock[0] 和 lock[1] 中。

有人可以告诉我,我在这段代码中做错了什么还是 strdup 的问题(分配了一个已经分配的内存块)

注意:当我将 char *name 更改为 char name[20] 而不是 strdup 时,我使用了 strcpy,它运行良好。

4

1 回答 1

2

错误的一个可能原因是您的分配:

*dlock = (isolock *)malloc((sizeof (*dlock)) * 3);

dlock是一个指向指针的指针,因此指针sizeof(*dlock)的大小与sizeof(struct isolock)(or sizeof(**dlock)) 不同。

于 2012-09-15T12:21:53.693 回答