c - 为什么我的 C 程序中会出现 "Program failed: Memory fault, core dumped"?

标签 c linux gcc memory-leaks gcc-warning

该程序从标准输入中读取文本,并构建包含输入中各个单词的二叉搜索树。该程序读取输入,直到没有更多数据可用,计算输入中每​​个单词的出现频率。一旦输入耗尽,将按顺序遍历树以生成按字母顺序排列的单词及其频率列表。

问题:我可以毫无错误地编译我的代码,当我运行 ./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

But whenever I submit it to the try server it tests the code and tells me that I didn't output anything, and that I had a "Program failed: Memory fault, core dumped", this is the output I am getting on page 1: Try Submission Output

This is my wordFreq.c file:

#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 页 上的测试链接: Valgrind Test Link

最佳答案

您的代码中存在一些问题:

  • 您包含非标准文件 <strings.h> , 但不是 <stdlib.h>其中 malloc()free()已声明。

  • 你永远不会检查 malloc()返回值。如果测试系统内存很少或配置为生成 malloc()尽早失败,这是可行的,您的程序将崩溃而不是报告错误。

  • 不要使用 strncpy((*root)->word, word, len);将字符串复制到分配的内存中。只需使用 strcpy因为你用 strlen(word) + 1 分配了足够的内存字节,或使用 strdup() . strncpy没有按照你的想法去做!它具有非常容易出错和被广泛误解的语义。切勿使用此功能。

  • main()函数,你应该使用 TreeNode *root;变量并将其地址传递给insert_word()而不是分配指针。

唯一严重的问题是上面的第二点,尽管它不太可能解释观察到的行为。

关于c - 为什么我的 C 程序中会出现 "Program failed: Memory fault, core dumped"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40008863/

相关文章:

c - 我有一个用 C 编写的竞赛程序,无论如何总是有相同的获胜者

linux - Arch Linux 中的 VMware 工具安装

linux - TI AM335x Linux板卡与Telit DE910模块如何建立ppp通信

c - 在 C 中定义 typedef 的错误

c - 没有明显段错误的编译器警告

c - STM32F103x_XL 闪存组 2 保持忙碌状态

c - GCC 对待 int i=048;作为一个错误,为什么 GCC 不能更智能呢?

linux - 如何从 auditctl 中删除规则

c - 如何获得有关分配给但不再使用的变量的警告?

c++ - CMake 正在删除预处理器定义