如何在此 C 代码中找到分段错误?

How can I find the segmentation fault in this c code?

当我运行程序输出时:

Process finished with exit code 139 (interrupted by signal 11: SIGSEGV) 我找不到问题。

我试过调试它,但我没有足够的 c 经验,无法找到错误。

代码应该做的是,首先随机创建一棵树,然后将所有节点的值相加。

此外,我真的需要知道如何编写更安全的 C 代码,而不会出现分段错误和此类问题。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>


/**
 * Tree structure, where there can be any number of children
 */
typedef struct Tree {

    /**
     * Value of current node
     */
    double value;

    /**
     * number of children
     */
    int n;

    /**
     * children
     */
    struct Tree **children;
} Tree;


Tree *create(double value, int n) {
    Tree *tree = (Tree*) malloc(sizeof(Tree));
    int i;

    *tree = (Tree) {
        .value = value,
        .n = n,
        .children = NULL
    };

    if (n) {
        tree->children = (Tree**) malloc(sizeof(Tree*));

        for (i = 0; i < n; i++) {
            tree->children[i] = NULL;
        }
    }

    return tree;
}


Tree *make_random_tree(int height) {
    double value;
    int n, i;
    Tree *tree;

    value = (rand() / (double) RAND_MAX) * 100.0;
    n = rand() % 10;


    if (height == 0) {
        return create(value, 0);
    }

    tree = create(value, n);

    for (i = 0; i < n; i++) {
       tree->children[i] = make_random_tree(height - 1);
    }

    return tree;
}


void delete(Tree *tree) {
    int i;

    if (tree == NULL) return;

    for (i = 0; i < tree->n; i++) {
        delete(tree->children[i]);
    }

    free(tree->children);
    free(tree);
}


double sum_tree_values(Tree *tree) {
    double sum = 0.0;
    int i;

    if (tree == NULL) return 0.0;

    sum += tree->value;
    for (i = 0; i < tree->n; i++) {
        sum += sum_tree_values(tree->children[i]);
    }

    return sum;
}


int main() {
    Tree *tree = make_random_tree(3);


    delete(tree);

    return 0;
}

您得到的错误是由于访问了不属于您的内存造成的。考虑使用 valgrind 来查找这些错误

在:

Tree *create(double value, int n) {
    Tree *tree = (Tree*) malloc(sizeof(Tree));
    int i;

    *tree = (Tree) {
        .value = value,
        .n = n,
        .children = NULL
    };

    if (n) {
        tree->children = (Tree**) malloc(sizeof(Tree*));

        for (i = 0; i < n; i++) {
            tree->children[i] = NULL;
        }
    }

    return tree;
}

你循环 n children 并将它们设置为 NULL 但你只分配了 1 child。您必须为所有 children:

分配 space

变化:

tree->children = (Tree**) malloc(sizeof(Tree*));

至:

tree->children = (Tree**) malloc(n * sizeof(Tree*));

进一步考虑使用 calloc 而不是 malloc 它会自动将所有 children 设置为 NULL.

所以代替:

if (n) {
        tree->children = (Tree**) malloc(n * sizeof(Tree*));

        for (i = 0; i < n; i++) {
            tree->children[i] = NULL;
        }
    }

使用:

if (n)
    tree->children = (Tree**) calloc(n, sizeof(Tree*));