我的链表有一些问题。我将struct dListNode
用作列表的节点,并将指针指向用作数据存储的struct data
。
struct data{
int payload;
};
struct dListNode{
struct dListNode *next;
struct dListNode *prev;
struct data *val;
}*dHead, *dTail;
我的程序编译得很好,但在下面的行中出现了分段错误。发生了什么事?
newDNode = (struct dListNode *)malloc(sizeof(struct dListNode)+sizeof(struct data));
printf("newnode createdn"); // this prints
newDNode->val->payload = rand() % 1000; //error here?
printf("newnode payload: %in", newDNode->val->payload); //seg fault before this is printed
此外,我已经在程序中运行了这一行:srand((unsigned)time(NULL))
NewDNode
没有相关的内存分配
newDNode = (struct dListNode *)malloc(sizeof(struct dListNode)+sizeof(struct data));
这只是将内存分配给newDnode
而不是newDnode->val
。由于newDNode->val
只包含该位置内存中剩余的内容(甚至可能是0(NULL指针((,并且您试图为既不在堆栈上也不在堆上的内存位置分配一个值,因此程序会抱怨,因为您试图访问未分配的内存部分。
以下是您应该做的:
newDNode = malloc(sizeof(struct dListNode));
newDnode->val = malloc(sizeof(struct data));
printf("newnode createdn");
newDNode->val->payload = rand() % 1000;
printf("newnode payload: %in", newDNode->val->payload);
作为提示,请始终尝试不强制转换malloc(或任何其他内存分配函数(返回的结果。这被认为是不好的做法。
您的问题是从未初始化指针val
:
newDNode->val->payload = rand() % 1000;
分配了newDNode
,但没有初始化任何字段,因此取消引用val
可能会导致分段错误。
因此,在访问val
之前,您需要为其分配一些内容。
newDNode = malloc(sizeof(struct dListNode)); // Allocate "dListNode"
newDNode->val = malloc(sizeof(struct data)); // Allocate "data"
newDNode->val->payload = rand() % 1000;
您对分配的工作方式有点误解。您需要分别分配每个指针。
编辑:另一种方法是首先不使用val
的指针:
// Declare struct as:
struct dListNode{
struct dListNode *next;
struct dListNode *prev;
struct data val;
}*dHead, *dTail;
// Build object like this:
newDNode = malloc(sizeof(struct dListNode));
newDNode->val.payload = rand() % 1000;
val
未指向有效的data
结构。当然,malloc
的大小足够了,但这并不意味着val
现在突然变成了一个有效的指针。您应该用dListNode
的大小初始化newDNode
,然后单独初始化newDNode->val
,以指向某个足够大的有效内存块,用于data
结构。
附带说明一下,您不需要强制转换malloc
的返回值。这是一个C++的东西;在C中,CCD_ 22可以隐式地转换为任何其他指针类型。
第二,如果您的结构类型为typedef
,那么在使用它们时不必到处写struct
。
您从未将newDNode->val
设置为指向任何对象。因此,当您尝试设置newDNode->val->payload
时,您正在取消引用空指针或某个随机地址(我忘记了是哪个(。这两种情况都不是你想要的。
我真的不喜欢在同一个语句中对两个结构进行malloc’in的想法。但如果你坚持这样做,你需要做一些类似的事情
newDNode->val = (struct data*)((char*) newDNode + sizeof(struct dListNode));
不过,更好的方法是更改结构,使val
是一个结构,而不仅仅是指向一个结构的指针。然后sizeof(struct dListNode)
包括struct data
的大小,您可以像newDListNode->val.payload
一样访问它,而不必单独对数据部分进行malloc或进行任何棘手的指针计算。(缺点是,您必须复制结构以将它们存储在阵列中,交换它们,等等(