为什么我的 C 程序中出现 "Program failed: Memory fault, core dumped"?
Why am I getting a "Program failed: Memory fault, core dumped" in my C program?
该程序从标准输入中读取文本并构建包含输入中各个单词的二叉搜索树。该程序读取输入,直到没有更多数据可用,计算输入中每个单词的出现频率。输入用完后,将按顺序遍历树以生成按字母顺序排列的单词列表及其频率。
问题: 我可以毫无错误地编译我的代码,当我 运行 ./wordFreq < input.1 时,它 运行 完美并且输出没有错误的正确答案...这是正确的输出:
additional 1
agree 3
another 3
don't 3
for 1
I 1
input 4
is 3
line 5
need 1
one 1
road 1
the 1
think 1
This 4
we 1
yet 1
you 3
但是每当我将它提交给 try 服务器 时,它会测试代码并告诉我我没有输出任何东西,而且我有一个 "Program failed: Memory fault, core dumped",这是我在 第 1 页 上得到的输出:
Try Submission Output
这是我的wordFreq.c文件:
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include "wordFreq.h"
#define UNUSED(p) ((void)(p))
// Creates a node for each unique word it is given, and then inserts this
// new node in the proper position in the binary search tree, updating
// whatever pointer is necessary.
//
// @param root a pointer to the variable which contains the pointer to the
// root-level node in the tree
// @param word a pointer to the NUL-terminated arrach of characters
void insert_word(TreeNode** root, const char *word){
if (*root == NULL){
*root = (TreeNode*)malloc(sizeof(TreeNode));
unsigned int len = strlen(word);
(*root)->word = (char *)malloc((len + 1) * sizeof(char));
strncpy((*root)->word, word, len);
(*root)->word[len] = 0;
(*root)->frequency = 1;
(*root)->left = NULL;
(*root)->right = NULL;
}
else{
int compare = strcasecmp(word, (*root)->word);
if (compare < 0){
insert_word(&((*root)->left), word);
} else if(compare> 0){
insert_word(&((*root)->right), word);
} else if(compare == 0){
(*root)->frequency++;
}
}
}
// Traverses the entire tree using an in-order traversal and will
// print th contents of each node as it is visited
//
// @param root a pointer to the root node of the tree
void traverse_tree(const TreeNode* root){
if (root == NULL)
return;
if (root != NULL){
traverse_tree(root->left);
printf("%s %d\n", root->word, root->frequency);
traverse_tree(root->right);
}
return;
}
// Deallocates all the nodes that were created in insert_node()
//
// @param a pointer to the root node of the tree
void cleanup_tree(TreeNode* root){
if (root == NULL)
return;
if (root->left != NULL){
cleanup_tree(root->left);
}
if(root->right != NULL){
cleanup_tree(root->right);
}
free(root->word);
free(root);
return;
}
int main(int argc, char* argv[]){
UNUSED(argv);
if (argc > 1)
printf("Usage: bst");
else{
FILE* pFile = fopen("input.1", "r");
char *buf = NULL;
size_t len = 0;
TreeNode** root = NULL;
if (!pFile){
printf("File not found");
} else{
root = (TreeNode**)malloc(sizeof(TreeNode*));
*root = NULL;
while (getline(&buf,&len,pFile) > 0){
char * pch;
pch = strtok(buf, " !@#$%^&*?.,:;\n");
while (pch !=NULL){
insert_word(root, pch);
pch = strtok(NULL, " !@#$%^&*,:;?.\n");
}
}
free(buf);
fclose(pFile);
traverse_tree(*root);
}
cleanup_tree(*root);
free(root);
}
return 0;
}
这是我的wordFreq.h文件:
#ifndef _BST_H_
#define _BST_H_
// The definition of the tree structure
typedef struct TreeNode_st {
char *word; // the word held in this node
unsigned int frequency; // how many times it has been seen
struct TreeNode_st *left; // node's left child
struct TreeNode_st *right; // node's right child
} TreeNode;
// FUNCTIONS ARE REQUIRED TO IMPLEMENT
// insert_word()
// Dynamically build BST by allocating nodes from the heap
//
// args -
// root - a pointer to the pointer to the root of the tree
// to build this tree on to.
// word - string containing the word to be inserted
void insert_word( TreeNode** root, const char *word );
// traverse_tree()
// Recursively traverses the tree and prints the value of each
// node.
//
// args -
// root - a pointer to the root of the tree to traverse
void traverse_tree( const TreeNode* root );
// cleanup_tree()
// Cleanup all memory management associated with the nodes on the heap
//
// args
// root - the current root of the tree
void cleanup_tree( TreeNode* root );
#endif // BST_H
这是输入文件(名为 input.1):
This is one input line.
This is another input line, don't you agree?
Another input line, don't you agree?
This is yet another input line, don't you agree?
I think we need this additional line for the road.
编译命令:
root@comp:~/Desktop/Homeworks/5$ gcc -ggdb -std=c99 -Wall -Wextra -pedantic -c wordFreq.c
root@comp:~/Desktop/Homeworks/5$ gcc -ggdb -std=c99 -Wall -Wextra -pedantic -o wordFreq wordFreq.o -lm
Valgrind 测试:我还使用以下命令测试了 valgrind 中的代码:
我没有发现任何错误...这是要在 第 2 页 上测试的 link:
Valgrind Test Link
您的代码存在一些问题:
您包含非标准文件 <strings.h>
,但不包含声明了 malloc()
和 free()
的 <stdlib.h>
。
您永远不会检查 malloc()
return 值。如果测试系统内存非常少或配置为使 malloc()
提前失败(这是可行的),您的程序将崩溃而不是报告错误。
不要使用strncpy((*root)->word, word, len);
将字符串复制到分配的内存中。只需使用 strcpy
,因为您分配了足够的 strlen(word) + 1
字节内存,或者使用 strdup()
。 strncpy
没有按照你的想法去做!它具有非常容易出错和被广泛误解的语义。切勿使用此功能。
在main()
函数中,您应该使用TreeNode *root;
变量并将其地址传递给insert_word()
,而不是分配指针。
唯一严重的问题是上面的第二点,尽管它不太可能解释观察到的行为。
该程序从标准输入中读取文本并构建包含输入中各个单词的二叉搜索树。该程序读取输入,直到没有更多数据可用,计算输入中每个单词的出现频率。输入用完后,将按顺序遍历树以生成按字母顺序排列的单词列表及其频率。
问题: 我可以毫无错误地编译我的代码,当我 运行 ./wordFreq < input.1 时,它 运行 完美并且输出没有错误的正确答案...这是正确的输出:
additional 1 agree 3 another 3 don't 3 for 1 I 1 input 4 is 3 line 5 need 1 one 1 road 1 the 1 think 1 This 4 we 1 yet 1 you 3
但是每当我将它提交给 try 服务器 时,它会测试代码并告诉我我没有输出任何东西,而且我有一个 "Program failed: Memory fault, core dumped",这是我在 第 1 页 上得到的输出: Try Submission Output
这是我的wordFreq.c文件:
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include "wordFreq.h"
#define UNUSED(p) ((void)(p))
// Creates a node for each unique word it is given, and then inserts this
// new node in the proper position in the binary search tree, updating
// whatever pointer is necessary.
//
// @param root a pointer to the variable which contains the pointer to the
// root-level node in the tree
// @param word a pointer to the NUL-terminated arrach of characters
void insert_word(TreeNode** root, const char *word){
if (*root == NULL){
*root = (TreeNode*)malloc(sizeof(TreeNode));
unsigned int len = strlen(word);
(*root)->word = (char *)malloc((len + 1) * sizeof(char));
strncpy((*root)->word, word, len);
(*root)->word[len] = 0;
(*root)->frequency = 1;
(*root)->left = NULL;
(*root)->right = NULL;
}
else{
int compare = strcasecmp(word, (*root)->word);
if (compare < 0){
insert_word(&((*root)->left), word);
} else if(compare> 0){
insert_word(&((*root)->right), word);
} else if(compare == 0){
(*root)->frequency++;
}
}
}
// Traverses the entire tree using an in-order traversal and will
// print th contents of each node as it is visited
//
// @param root a pointer to the root node of the tree
void traverse_tree(const TreeNode* root){
if (root == NULL)
return;
if (root != NULL){
traverse_tree(root->left);
printf("%s %d\n", root->word, root->frequency);
traverse_tree(root->right);
}
return;
}
// Deallocates all the nodes that were created in insert_node()
//
// @param a pointer to the root node of the tree
void cleanup_tree(TreeNode* root){
if (root == NULL)
return;
if (root->left != NULL){
cleanup_tree(root->left);
}
if(root->right != NULL){
cleanup_tree(root->right);
}
free(root->word);
free(root);
return;
}
int main(int argc, char* argv[]){
UNUSED(argv);
if (argc > 1)
printf("Usage: bst");
else{
FILE* pFile = fopen("input.1", "r");
char *buf = NULL;
size_t len = 0;
TreeNode** root = NULL;
if (!pFile){
printf("File not found");
} else{
root = (TreeNode**)malloc(sizeof(TreeNode*));
*root = NULL;
while (getline(&buf,&len,pFile) > 0){
char * pch;
pch = strtok(buf, " !@#$%^&*?.,:;\n");
while (pch !=NULL){
insert_word(root, pch);
pch = strtok(NULL, " !@#$%^&*,:;?.\n");
}
}
free(buf);
fclose(pFile);
traverse_tree(*root);
}
cleanup_tree(*root);
free(root);
}
return 0;
}
这是我的wordFreq.h文件:
#ifndef _BST_H_
#define _BST_H_
// The definition of the tree structure
typedef struct TreeNode_st {
char *word; // the word held in this node
unsigned int frequency; // how many times it has been seen
struct TreeNode_st *left; // node's left child
struct TreeNode_st *right; // node's right child
} TreeNode;
// FUNCTIONS ARE REQUIRED TO IMPLEMENT
// insert_word()
// Dynamically build BST by allocating nodes from the heap
//
// args -
// root - a pointer to the pointer to the root of the tree
// to build this tree on to.
// word - string containing the word to be inserted
void insert_word( TreeNode** root, const char *word );
// traverse_tree()
// Recursively traverses the tree and prints the value of each
// node.
//
// args -
// root - a pointer to the root of the tree to traverse
void traverse_tree( const TreeNode* root );
// cleanup_tree()
// Cleanup all memory management associated with the nodes on the heap
//
// args
// root - the current root of the tree
void cleanup_tree( TreeNode* root );
#endif // BST_H
这是输入文件(名为 input.1):
This is one input line. This is another input line, don't you agree? Another input line, don't you agree? This is yet another input line, don't you agree? I think we need this additional line for the road.
编译命令:
root@comp:~/Desktop/Homeworks/5$ gcc -ggdb -std=c99 -Wall -Wextra -pedantic -c wordFreq.c root@comp:~/Desktop/Homeworks/5$ gcc -ggdb -std=c99 -Wall -Wextra -pedantic -o wordFreq wordFreq.o -lm
Valgrind 测试:我还使用以下命令测试了 valgrind 中的代码:
我没有发现任何错误...这是要在 第 2 页 上测试的 link: Valgrind Test Link
您的代码存在一些问题:
您包含非标准文件
<strings.h>
,但不包含声明了malloc()
和free()
的<stdlib.h>
。您永远不会检查
malloc()
return 值。如果测试系统内存非常少或配置为使malloc()
提前失败(这是可行的),您的程序将崩溃而不是报告错误。不要使用
strncpy((*root)->word, word, len);
将字符串复制到分配的内存中。只需使用strcpy
,因为您分配了足够的strlen(word) + 1
字节内存,或者使用strdup()
。strncpy
没有按照你的想法去做!它具有非常容易出错和被广泛误解的语义。切勿使用此功能。在
main()
函数中,您应该使用TreeNode *root;
变量并将其地址传递给insert_word()
,而不是分配指针。
唯一严重的问题是上面的第二点,尽管它不太可能解释观察到的行为。