我的链接列表存在一些问题。我将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 created\n"); // this prints
newDNode->val->payload = rand() % 1000; //error here?
printf("newnode payload: %i\n", newDNode->val->payload); //seg fault before this is printed
另外,我已经在程序中运行了这一行:srand((unsigned)time(NULL))
答案 0 :(得分:3)
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 created\n");
newDNode->val->payload = rand() % 1000;
printf("newnode payload: %i\n", newDNode->val->payload);
作为提示,总是尝试不转换malloc(或任何其他内存分配函数)返回的结果。它被认为是不好的做法。
答案 1 :(得分:2)
问题是你从未初始化指针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;
答案 2 :(得分:1)
val
未指向有效的data
结构。当然,你malloc
的大小足够了,但这并不意味着val
现在突然成为一个有效的指针。您应该使用newDNode
的大小初始化dListNode
,然后单独初始化newDNode->val
以指向足够大的data
结构的一些有效内存块。
在旁注中,您不需要转换malloc
的返回值。这是一个C ++的东西;在C中,void*
可以隐式转换为任何其他指针类型。
其次,如果你typedef
你的结构类型,你在使用它们时不必在整个地方写struct
。
答案 3 :(得分:0)
您永远不会将newDNode->val
设置为指向任何内容。因此,当您尝试设置newDNode->val->payload
时,您将取消引用空指针或某个随机地址(我忘记了哪个)。这两种情况都不是你想要的。
我真的不喜欢在同一个语句中同时使用malloc的结构。但如果你坚持这样做,你需要做一些像
这样的事情newDNode->val = (struct data*)((char*) newDNode + sizeof(struct dListNode));
但是,更好的方法是更改结构,以便val
是结构而不仅仅是指向结构的结构。然后sizeof(struct dListNode)
包含struct data
的大小,你可以像newDListNode->val.payload
一样访问它,而不必单独malloc数据部分或做任何棘手的指针数学运算。 (缺点是,你必须复制结构以将它们存储在一个数组中,交换它们等等。)