如何在此 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*));
当我运行程序输出时:
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:
变化:
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*));