C递归地展平节点列表

时间:2015-02-13 17:13:54

标签: c recursion pass-by-reference valgrind dataflow

我遇到了一些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第一篇文章,如果我违反任何行为准则,请告诉我:)。

0 个答案:

没有答案