gpt4 book ai didi

c - 在解析树中打印第三个字符串时出现段错误

转载 作者:太空宇宙 更新时间:2023-11-04 01:08:20 25 4
gpt4 key购买 nike

我正在创建一个编译器,并开始创建我的解析树结构。

我有一个可以包含或不包含子节点的“节点”。

typedef struct Node {
int node_type;
union {
char* string;
int number;
struct Node* nodes;
} node_data;
} Node;

然后这些函数组装/打印它

Node* MakeNodeFromString(char* mystring) {
Node* mynode = (Node*) malloc(sizeof(Node));
mynode->node_data.string = strdup(mystring);
mynode->node_type = 0; // @TODO not 3
return mynode;
}

Node* MakeTwoBranchNode(int nodetype, Node* a, Node* b) {
Node* mynode = (Node*) malloc(sizeof(Node));
mynode->node_type = 2; // @TODO not 3
mynode->node_data.nodes = malloc(2 * sizeof(Node*));
mynode->node_data.nodes[0] = *a; mynode->node_data.nodes[1] = *b;
return mynode;
}

void printtree (Node *n, int level) {
if (!n) return;

printf ("start %d\n", n->node_type);
switch (n->node_type) {
case 2:
printf ("%*c2\n", level, ' ');
printtree (&n->node_data.nodes[0], level+1);
printtree (&n->node_data.nodes[1], level+1);
break;
case 0:
printf ("%*c%s\n", level, ' ', n->node_data.string);
break;
}
printf ("end %d\n", n->node_type);
}

每当我组装一棵树时,我都会遇到 printf'ing 或 strlen'ing 我的字符串的段错误。我已经尝试过 strdup、strcpy 等。我很确定失败的不是 MakeTwoBranchNode,因为我可以创建大量的数字树(不包括代码)。但我不确定。

这是一个代码示例,说明它在我的机器上发生和不发生段错误的地方

int main() {
// Works
printtree(
MakeTwoBranchNode(3,
MakeNodeFromString("first string"),
MakeNodeFromString("second string")
),
1
);
// Fails
printtree(
MakeTwoBranchNode(3,
MakeTwoBranchNode(3,
MakeNodeFromString("first string"),
MakeNodeFromString("second string")
),
MakeNodeFromString("third string")
),
1
);
}

如果您运行此示例(并且可以理解其神秘的输出),您将在 printf(n->node_data.string) 期间看到它的段错误。

最佳答案

您分配的是 sizeof-a-pointer,而不是 sizeof-a-node:

Node* MakeTwoBranchNode(int nodetype, Node* a, Node* b) {
Node* mynode = malloc(sizeof(Node));
mynode->node_type = 2; // @TODO not 3
mynode->node_data.nodes = malloc(2 * sizeof(Node*)); // HERE
mynode->node_data.nodes[0] = *a; mynode->node_data.nodes[1] = *b;
return mynode;
}

您可以将上面的注释行更改为:

    mynode->node_data.nodes = malloc(2 * sizeof(Node));

但是,正如您编写的测试程序一样,内存泄漏。您为传递MakeTwoBranchNode() 的节点分配的内存会发生什么变化?这不是我认为您真正想要的。首先最好使用指针数组。

typedef struct Node {
int node_type;
union {
char* string;
int number;
struct Node *nodes[2];
} node_data;
} Node;

然后保存传递给 MakeTwoBranchNode 的实际指针。在这样做时,您将这些节点的所有权传递给双分支节点(因此您还应该确保在释放它时它会正确清理其子节点):

Node* MakeTwoBranchNode(int nodetype, Node* a, Node* b) {
Node* mynode = malloc(sizeof(Node));
mynode->node_type = 2; // @TODO not 3
mynode->node_data.nodes[0] = a;
mynode->node_data.nodes[1] = b;
return mynode;
}

现在没有内存泄漏,除非您未能free() nodes[0]nodes[1] 中的指针,当您'正在破坏双分支节点。

关于c - 在解析树中打印第三个字符串时出现段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18675995/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com