具有指向另一个结构的指针的结构中的分段错误

时间:2011-11-11 00:09:21

标签: c linked-list segmentation-fault

我的链接列表存在一些问题。我将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))

4 个答案:

答案 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数据部分或做任何棘手的指针数学运算。 (缺点是,你必须复制结构以将它们存储在一个数组中,交换它们等等。)