我正在编写一个程序,它读取一个字典文件(文本文件,每行一个单词),并将其插入到由数组的“链表”组成的结构中,其中该单词以递归方式转发到[第一个字母] - 'a']数组的条目(这是另一个数组,处理下一个字母)。当整个单词被“消耗”时,它将单词(未更改)插入到常规的单词列表中。该程序成功处理前15个单词,但在第16个单词时会抛出分段错误。
以下代码段中的add()方法中出现了分段错误:
struct LinkedList * new = (struct LinkedList *) calloc(1,
sizeof(struct LinkedList));
if (!new) {
perror("Not enough memory!"); // Error here
exit(2);
}
(希望)相关代码:
void addList (struct LinkedList * list, char * word) {
if (!list->next)
{
struct LinkedList * new = malloc(sizeof(struct LinkedList));
if (!new) {
perror("Not enough memory!");
exit(2);
}
char * new_word = malloc(strlen(word) * sizeof(char));
if (!new_word) {
fprintf(stderr, "Not enough memory!");
exit(2);
}
new->next = 0;
strcpy(new_word, word);
new->word = new_word;
list->next = new;
}
else
{
addList(list->next, word);
}
}
void add(struct HashTree * root, char * word, char * word_sorted, int length) {
if (length == 0) // Found the correct place
{
if (!root->words) // If words are not allocated
{
// Create list node
struct LinkedList * new = calloc(1, sizeof(struct LinkedList));
if (!new) {
perror("Not enough memory!");
exit(2);
}
char * new_word = malloc(strlen(word) * sizeof(char));
if (!new_word) {
fprintf(stderr, "Not enough memory!");
exit(2);
}
new->next = 0;
strcpy(new_word, word);
new->word = new_word;
root->words = new;
}
else // Add to the Linked List
{
addList(root->words, word);
}
}
else
{
// printf("Length_add = %d\n", length);
if (!root->next) // If the array was not allocated yet
{
struct HashTree * new = malloc(27 * sizeof(struct HashTree *));
if (!new) {
perror("Not enough memory!");
exit(2);
}
root->next = new;
}
add(&(root->next[ word_sorted[0] - 'a' ]),
word, (char *) (word_sorted +1), (length-1)); // Use the next letter.
}
}
要保存空间Here is the link to the full code.
这是gdb core和backtrace的输出:
Program terminated with signal SIGSEGV, Segmentation fault.
100 perror("Not enough memory!");
之前我在Java中实现了类似的算法,算法似乎是正确的。我对C很陌生,不明白可能出错。我真的很感激任何帮助!
编辑: 删除sort,clean和cleanWords方法(它们不会极大地影响将单词添加到结构中)。处理第二个单词时发生了分段,第125行:
perror("Dictionary file not found!");
答案 0 :(得分:2)
在else
的主add()
子句中,您会分配一些内存,但不要初始化它。然后在下一次递归调用add()
时使用未初始化的内存。至少使用calloc()
代替malloc()
。你还为你的结构分配了27个指针,但是你正在使用它,好像你分配了27个结构一样。
错:
struct HashTree * new = malloc(27 * sizeof(struct HashTree *));
右:
struct HashTree *new = calloc(27, sizeof(struct HashTree));
或者:
struct HashTree *new = calloc(27, sizeof(*new));
此外,在addList()
和add()
中,您没有为字符串分配足够的空间;你忘记了尾随的空格。
错:
char *new_word = (char *) malloc(length * sizeof(char));
右:
char *new_word = (char *) malloc(length + 1);
我不会在我的C代码中使用C ++关键字,因此我会使用new_hash
或其左右而不只是new
。许多人会因为分配的演员而鞭挞你。
通过这些更改,代码对我来说已经完成了。它像愤怒一样泄露,但这完全是预期的。
答案 1 :(得分:0)
对于这样的错误,问题几乎总是fopen
的问题。如果我是对的,您可能忘记将扩展名添加到文件中,或者这可能是您正在使用的文件路径的问题。
我的建议:
使用ctrl + f查找"/usr/share/dict/words"
的所有实例,然后验证它们是否引用了正确的文件。
修改强>
要特别注意第184行。我怀疑"/usr/share/dict/words.txt"
应该是while(fgets(word, sizeof(word), dict) != NULL) {
编辑2:
而不是(第200行):
while(!feof(dict)) {
fscanf(dict, "%*[^']", MAX_WORD_LENGTH, word);
尝试fscanf
:
int fscanf( FILE *restrict stream, const char *restrict format, ... );
修改强>
谢谢@JonathanLeffler我仍然会推荐fscanf
fscanf
如果使用得当,fscanf(dict, "%*s", MAX_WORD_LENGTH, word);
fscanf(dict, "'", MAX_WORD_LENGTH, word);//get rid of the delimiter
在阅读格式化数据时非常有用。
{{1}}