C字符数组在传递到函数后损坏
我正在尝试实现一个类似于20个问题的程序,在这个程序中,问题和答案猜测的文本文件被加载,复制到一个字符数组中(其中新的空格行被“/0”替换,以便将问题拆分为单个字符串)。将文本文件复制到数组中后,该数组工作正常。建立了一个树结构,将短语组织到yes/no问题树中,左边的子项是yes响应,右边的子项是no响应,左边的子项是猜测,程序在最后用以猜测 我遇到的问题是,在构建树(从InitTree调用treeBuilder)之后,复制文本文件中短语的数组的内容被破坏 在调用InitTree之前,数组内容如下所示: 它毛茸茸的吗?它会喵喵叫吗?猫狗它有獠牙吗?它有大耳朵吗?大象犀牛鳄鱼 调用后,它看起来如下所示: 它毛茸茸的吗?-?“?狗有獠牙吗?它有大耳朵吗?大象犀牛鳄鱼 我一直在测试它在哪里停止工作,在treeBuilder中,数组的所有元素都完好无损,但是一旦对treeBuilder的函数调用结束,数组就会损坏。我已经尝试过在分配内存时使用calloc来保护内存,甚至是使字符数组保持静态,这与发生这种情况的情况类似。但我所有的预防措施似乎都不起作用,我也不确定问题出在哪里。我已经尝试过在stackoverflow上查看类似的案例,但我找不到与我的问题相关的任何东西 由于明显的原因,当程序实际开始使用树时,这最终会导致seg故障 我试过运行gdb,但不管出于什么原因,它都不会让我逐行检查,因为它找不到行信息,只会跳过所有内容,直到它提示输入,或者得到内存错误或其他信息,所以在这里运行gdb不是很有帮助。我猜这可能是因为主函数在包含的文件或其他文件中。但这不是重点 以下是与此问题相关的代码:C字符数组在传递到函数后损坏,c,arrays,pointers,tree,char,C,Arrays,Pointers,Tree,Char,我正在尝试实现一个类似于20个问题的程序,在这个程序中,问题和答案猜测的文本文件被加载,复制到一个字符数组中(其中新的空格行被“/0”替换,以便将问题拆分为单个字符串)。将文本文件复制到数组中后,该数组工作正常。建立了一个树结构,将短语组织到yes/no问题树中,左边的子项是yes响应,右边的子项是no响应,左边的子项是猜测,程序在最后用以猜测 我遇到的问题是,在构建树(从InitTree调用treeBuilder)之后,复制文本文件中短语的数组的内容被破坏 在调用InitTree之前,数组内容
struct treeStruct {
char *string;
struct treeStruct *left, *right;
};
typedef struct treeStruct *TreeType;
// Builds a tree
void treeBuilder(TreeType tree, char **phrase, long level){
// Gets the level (number of tabs) of the next phrase
long nextLevel = countTabs(*phrase + strlen(*phrase) + 1);
tree->string = *phrase + level; // Assigns the response pointer to the tree array
// Move the pointer to the next string, since the the strings need to be
// put into the tree in linear order
(*phrase) += strlen(*phrase) + 1;
if (level >= nextLevel){
// Compares the current level with the level of the next string
// to determine if returning up the tree is necessary;
// This should be the answer to a question.
tree->left = NULL;
tree->right = NULL;
return;
}
else{
// Makes sure the left and right pointers of the struct have
// allocated space
tree->left = calloc(1, sizeof(TreeType));
tree->right = calloc(1, sizeof(TreeType));
// Adds the yes and no branches to the tree, recursion will take care
// of adding sub-branches
treeBuilder(tree->left, phrase, level + 1);
treeBuilder(tree->right, phrase, level + 1);
}
return;
}
TreeType InitTree (char *file){
if(file == NULL){
printf("File '%s' does not exist.\n", file);
exit(2);
}
FILE *fp;
fp = fopen(file, "r");
// Create a space in memory for the loaded questions to occupy
static char *phrases;
phrases = (char *)malloc(MAXSTR * MAXNUMQS * sizeof(char));
copyText(fp, phrases);
fclose(fp);
// Create space in memory for the tree structure
TreeType tree;
tree = (TreeType) calloc(1, sizeof(TreeType));
// Create a pointer to a pointer so that treeBuilder can
// change what the first pointer is pointing to, so the strings in
// phrases can be added in order throughout the recursion
static char *phrase_ptr, **phrase_ptr2;
phrase_ptr = &phrases[0];
phrase_ptr2 = &phrase_ptr;
//Build the tree
treeBuilder(tree, phrase_ptr2, 0);
topNode = tree;
return tree;
}
对不起,如果这是tl;dr,但我想尽可能清楚地说明我的问题。我注意到的一件事是,您使用的是
sizeof(TreeType)
,但是TreeType
是指向结构的指针,而不是结构本身。这意味着您正在创建一个不指向任何地方的指针,取消引用该指针将导致未定义的行为。在阅读了问题的其余部分后,这肯定可以解释SEG的错误
我认为您最好不要将结构类型定义为指针,并在使用指针时更加明确
例如
这里有一个关于类型定义指针的示例。似乎在C语言中比较常见,用于暗示数据类型是不透明的,用户不应取消引用(仅通过用户传递给的API调用取消引用)。如果您能提供所谓的示例,那就太好了。最小但可编译的代码仍然可以重现您的问题。这也可能有助于你自己找到bug。在这里,你打开一个文件,用一个我们根本看不到的函数读取它。相反,可以将字符串常量strcpy转换为
短语
。当你递归时,你真的想要级别+1
?或者您以前计算的nextLevel
?我通常会这样做,但我正在做的赋值要求树型是指针。@jtcramer:也许赋值的目的是教您不要将指针隐藏在typedefs后面?使用sizeof(struct TreeType)
轻松分配内存。实际上,这似乎是问题的根源。我将sizeof(TreeType)改为sizeof(treeStruct),似乎解决了这个问题。谢谢
typedef struct treeStruct TreeType;
void treeBuilder(TreeType *tree, char **phrase, long level){
...
if (!tree->left) {
// calloc returns a pointer to a new bit of memory that has been
// assigned on the heap
TreeType *temp = calloc(1, sizeof(TreeType));
// assignments below not explicitly needed as you're using calloc
temp->string = NULL;
temp->left = NULL;
temp->right = NULL;
tree->left = temp;
}
...
}