我遇到了一些C内存错误我真的很想弄清楚。我是C的新手,我们在编译器设计中使用它,我非常喜欢这种语言,指针非常有趣。
我想要完成的任务是递归地下降树并简化它,我被困在列表上。
该列表定义如下:statement_list - > statement_list语句|声明
目标是创建一个带有许多语句子节点的statement_list节点,展平递归定义的结构
这个想法是利用列表的结构如下:当找到一个语句列表时,我定义了一个指针数组,然后下降到左边的statement_list节点,直到只有一个子节点,然后分配数组并填写我提升的陈述。这样我只需要分配一次。我希望代码能让它更清晰一点:
// Takes a list, truncates all list children into a node array
void list_flatten ( Node_t* root, int depth ){
fprintf(stderr, "## List flatten ##\n");
// We allocate a reference to the array
Node_t** array = malloc(sizeof(Node_t**));
int size = 0;
// We start the recursive call
left_flatten( root, 0, &array, &size, depth );
root->children = array;
root->n_children = size;
}
void left_flatten ( Node_t* root, int counter, Node_t*** array_ptr, int* size, int depth ){
// This is for testing
if(outputStage == 4)
printf( "%*cSimplify %s \n", depth, ' ', root->nodetype.text );
// We increment size
(*size)++;
// If there is only one child we know we are at the last statement_list, so we extract the statement
if(root->n_children == 1){
node_t** array = *array_ptr;
*array = malloc((*size)*sizeof(Node_t*));
Node_t* test = root->children[0]->simplify(root->children[0], depth + 1);
fprintf(stderr, "Adding a %s to index %d\n", root->children[0]->nodetype.text, 0 );
*(array + 0) = test;
}
// If else we keep descending
else{
// We make a nother recursive call
left_flatten( root->children[0], counter + 1, array_ptr, size, depth + 1);
// The recursive call wil lhave allocated the memory we need
node_t** array = *array_ptr;
int index = *size - counter - 1;
// We fire off the recursive simplification for the right child
Node_t* test = root->children[1]->simplify(root->children[1], depth + 1);
fprintf(stderr, "Adding a %s to index %d\n", root->children[1]->nodetype.text, index );
*(array + index) = test;
}
}
它完成了我试图解析的30个程序中的28个,遇到了一些神秘的seg错误,所以我试图用valgrind找出发生了什么,并得到了下面的日志:
## List flatten ##
Adding a STATEMENT to index 0
Adding a STATEMENT to index 1
==19604== Invalid write of size 8
==19604== at 0x406CF8: left_flatten (simplifynodes.c:271)
==19604== by 0x406C63: left_flatten (simplifynodes.c:261)
==19604== by 0x406C63: left_flatten (simplifynodes.c:261)
==19604== by 0x406C63: left_flatten (simplifynodes.c:261)
==19604== by 0x406C63: left_flatten (simplifynodes.c:261)
==19604== by 0x406C63: left_flatten (simplifynodes.c:261)
==19604== by 0x406C63: left_flatten (simplifynodes.c:261)
==19604== by 0x406C63: left_flatten (simplifynodes.c:261)
==19604== by 0x406C63: left_flatten (simplifynodes.c:261)
==19604== by 0x406C63: left_flatten (simplifynodes.c:261)
==19604== by 0x406C63: left_flatten (simplifynodes.c:261)
==19604== by 0x406C63: left_flatten (simplifynodes.c:261)
==19604== Address 0x520d5b8 is 0 bytes after a block of size 8 alloc'd
==19604== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==19604== by 0x406AFD: list_flatten (simplifynodes.c:228)
==19604== by 0x40691B: simplify_list (simplifynodes.c:176)
==19604== by 0x4067C5: simplify_function (simplifynodes.c:75)
==19604== by 0x406A33: left_flatten_null (simplifynodes.c:211)
==19604== by 0x406964: list_flatten_null (simplifynodes.c:197)
==19604== by 0x4068F5: simplify_list_with_null (simplifynodes.c:168)
==19604== by 0x406E21: simplify_children (simplifynodes.c:296)
==19604== by 0x4065E4: simplify_default (simplifynodes.c:28)
==19604== by 0x4010BE: main (vslc.c:95)
==19604==
Adding a STATEMENT to index 2
Adding a STATEMENT to index 3
Adding a STATEMENT to index 4
Adding a STATEMENT to index 5
Adding a STATEMENT to index 6
Adding a STATEMENT to index 7
Adding a STATEMENT to index 8
Adding a STATEMENT to index 9
Adding a STATEMENT to index 10
Adding a STATEMENT to index 11
Adding a STATEMENT to index 12
Adding a STATEMENT to index 13
// Takes a list, truncates all list children into a node array
void list_flatten ( Node_t* root, int depth ){
fprintf(stderr, "## List flatten ##\n");
// We allocate a reference to the array
Node_t** array = malloc(sizeof(Node_t**));
int size = 0;
// We start the recursive call
left_flatten( root, 0, &array, &size, depth );
root->children = array;
root->n_children = size;
}
void left_flatten ( Node_t* root, int counter, Node_t*** array_ptr, int* size, int depth ){
// This is for testing
if(outputStage == 4)
printf( "%*cSimplify %s \n", depth, ' ', root->nodetype.text );
// We increment size
(*size)++;
// If there is only one child we know we are at the last statement_list, so we extract the statement
if(root->n_children == 1){
node_t** array = *array_ptr;
*array = malloc((*size)*sizeof(Node_t*));
Node_t* test = root->children[0]->simplify(root->children[0], depth + 1);
fprintf(stderr, "Adding a %s to index %d\n", root->children[0]->nodetype.text, 0 );
*(array + 0) = test;
}
// If else we keep descending
else{
// We make a nother recursive call
left_flatten( root->children[0], counter + 1, array_ptr, size, depth + 1);
// The recursive call wil lhave allocated the memory we need
node_t** array = *array_ptr;
int index = *size - counter - 1;
// We fire off the recursive simplification for the right child
Node_t* test = root->children[1]->simplify(root->children[1], depth + 1);
fprintf(stderr, "Adding a %s to index %d\n", root->children[1]->nodetype.text, index );
*(array + index) = test;
}
}
当我尝试释放节点时,程序也爆炸性地爆发,我认为这与底层内存问题有关。我最初使用常规双指针实现它,但我得到了相同的结果。
我可能只是以一种效率较低的方式重做它,因为我们有一个交付截止日期并且已经评分,但我确实想知道这里发生了什么,因为它可能会增加一些见解。如果有人想要所有的代码只是这样说,我会上传它。 PS第一篇文章,如果我违反任何行为准则,请告诉我:)。