2016-10-12 4 views
1

このプログラムは、標準入力からテキストを読み込み、入力から個々の単語を含むバイナリ検索ツリーを構築します。プログラムは、データが利用できなくなるまで入力を読み取り、入力内の各単語の出現頻度を数えます。入力が使い尽くされると、ツリーは順序通りのトラバーサルでトラバースされ、その頻度でアルファベット順の単語リストが生成されます。Cプログラムで「プログラムが失敗しました:メモリフォルト、コアがダンプされました」というメッセージが表示されるのはなぜですか?

問題:私はエラーなしで私のコードをコンパイルすることができますし、私は./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 

しかし、私はトライサーバーに提出したときに、それはコードをテストし、私は何も出力しなかったことを私に伝え、私がいたことを「プログラムが失敗しました:メモリ障害を、コアダンプ」、これは私が乗っている出力ページ1Try Submission Output

これは私のwordFreq.cファイルです:これは、入力ファイル(名前はinput.1)である

#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 

:これは私のwordFreq.hファイルです

#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, " [email protected]#$%^&*?.,:;\n"); 
       while (pch !=NULL){ 
        insert_word(root, pch); 
        pch = strtok(NULL, " [email protected]#$%^&*,:;?.\n"); 
       } 
      } 
      free(buf); 
      fclose(pFile); 
      traverse_tree(*root); 
     } 
     cleanup_tree(*root); 
     free(root); 

    } 
    return 0; 
}  

 
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. 

コンパイルコマンド:

 
[email protected]:~/Desktop/Homeworks/5$ gcc -ggdb -std=c99 -Wall -Wextra -pedantic -c wordFreq.c 
[email protected]:~/Desktop/Homeworks/5$ gcc -ggdb -std=c99 -Wall -Wextra -pedantic -o wordFreq wordFreq.o -lm 

Valgrindのテスト:私は、コマンドを使用してvalgrindの中でコードをテストした: Valgrind Test Link

+0

同じコードが2つの異なる動作を公開すると、私は鼻の悪魔を疑うでしょう。 – Jack

+1

あなたのシステムで真剣に 'ルート'としてプログラミングしていますか? – chqrlie

+0

@chqrlieいいえ私は機密目的でこれを変更しました – ShaolinGOD

答えて

0

あなたを:

私はエラーを得なかった...ここページ2でテストするためのリンクですあなたのコードにいくつかの問題があります:

  • 標準以外のファイル<strings.h>ですが、<stdlib.h>ではなく、malloc()free()が宣言されています。

  • 戻り値は決してチェックしないでください。malloc()戻り値。テストシステムにメモリがほとんどない場合や、malloc()が早く失敗するように設定されている場合は、エラーを報告する代わりにプログラムがクラッシュします。

  • strncpy((*root)->word, word, len);を使用して、割り当てられたメモリに文字列をコピーしないでください。十分なメモリをstrlen(word) + 1バイトで割り当てたか、strdup()を使用したので、strcpyを使用してください。 strncpyはあなたの考えをしません!エラーが発生しやすく、広く誤解されているセマンティクスがあります。この機能を使用しないでください。

  • main()関数では、TreeNode *root;変数を使用し、ポインタを割り当てる代わりにinsert_word()にそのアドレスを渡す必要があります。

重要な唯一の深刻な問題は、上記の2番目の点ですが、観察される動作を説明することはできません。

+0

malloc()を確認するにはどうすればよいですか?私はちょうどポインタを使用し始めました。 – ShaolinGOD

+0

@ShaolinGOD: 'malloc()'戻り値をポインタに格納した後、このポインタが 'NULL'であるかどうかをテストし、関数を正常に終了するか、メモリ不足状態を示すエラーメッセージで中止します。 – chqrlie

関連する問題