读取2kb txt文件(c)时出现分段错误

时间:2019-01-14 17:54:24

标签: c file segmentation-fault fopen

以下是从文件读取并将所述文件的每个字符串保存到二进制搜索树的代码。对于1KB的txt文件,它工作正常,但是当尝试使用更大的文件(2kb)时,我遇到了分段错误。

#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h> 
#include <string.h> 

typedef struct listNode ListNode;


struct listNode {
  int id;
  ListNode *next;
};

typedef struct treeNode TreeNode;


struct treeNode {
  char *word;
  char *key;
  int freq;
  ListNode *head;   
  TreeNode *left;
  TreeNode *right;
};

TreeNode* insertItem(TreeNode *root, char *gword);
void printTreeInorder(TreeNode *v);
void searchforexist(TreeNode *root, char *key);

#define MAX 25
int main()
{
   
    char word[MAX];
    TreeNode *root = NULL;
    
    
   
    FILE *fp=fopen("input.txt","r");

     if (fp!=NULL)
    {
      
        while (fscanf(fp,"%s \n",word) != EOF)
         {
              
            root = insertItem(root,word); 

          if (strcmp(word, "eof")==0)
            break;
          }
     }
    fclose(fp);


    printTreeInorder(root);
    printf("\n");
   
    return 0;
}


TreeNode* insertItem(TreeNode *root, char *gword)
{
   TreeNode *v = root;  
   TreeNode *pv = NULL; 
   while (v != NULL)
   {
      pv = v;
      int comp = strcmp(gword, v->word);
      if (comp < 0) v=v->left;
      else if (comp > 0) v=v->right;
      else
      {
         
          
         char *key=v->word;
         searchforexist(root,key);
          return root;
      }
   }

   TreeNode *tmp = (TreeNode *) malloc(sizeof(TreeNode));
   tmp->word=strdup(gword); 
   tmp->left=tmp->right=NULL;
   tmp->freq=1;
   

   if (root != NULL)
   {
      if (strcmp(gword, pv->word) < 0) pv->left=tmp;
         else pv->right=tmp;
   } else root=tmp;

   return root;

}



void searchforexist(TreeNode *root, char *key)
{
   if (root == NULL || root->key == key) 
       root->freq ++; 
     
    
    if (root->key < key) 
       searchforexist(root->right, key); 
  
    
     searchforexist(root->left, key); 
 } 




void printTreeInorder(TreeNode *v)
{
    if (v==NULL) return;

    printf("(");
    printTreeInorder(v->left);
    printf(")");

    printf(" %.4s ", v->word);

    printf("(");
    printTreeInorder(v->right);
    printf(")");
}

按预期运行的Txt文件: { 该测试文件中的单词用于测试钱包 将字符串传输到数据结构中。 }

但是,如果我将其更改为此,则会出现细分错误: { 该测试文件中的单词用于测试钱包 将字符串传输到数据结构中。 和 该测试文件中的单词用于测试钱包 将字符串传输到数据结构中。 }

1 个答案:

答案 0 :(得分:1)

一种简单的方法是使用gdb / lldb。

我编译了代码,并进行了调试:

$ g++ -g -ggdb test.cc
$ lldb a.out
(lldb) r
Process 83386 launched: '/path/to/a.out' (x86_64)
Process 83386 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x10)
    frame #0: 0x0000000100000ec1 a.out`searchforexist(root=0x0000000000000000, key="<link") at test.cc:104
   101  void searchforexist(TreeNode *root, char *key)
   102  {
   103     if (root == NULL || root->key == key)
-> 104         root->freq ++;
   105
   106
   107      if (root->key < key)
Target 0: (a.out) stopped.
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x10)
  * frame #0: 0x0000000100000ec1 a.out`searchforexist(root=0x0000000000000000, key="<link") at test.cc:104
    frame #1: 0x0000000100000eed a.out`searchforexist(root=0x0000000100102e50, key="<link") at test.cc:108
    frame #2: 0x0000000100000efe a.out`searchforexist(root=0x0000000100102b00, key="<link") at test.cc:111
    frame #3: 0x0000000100000d34 a.out`insertItem(root=0x0000000100102b00, gword="<link") at test.cc:78
    frame #4: 0x0000000100000c28 a.out`main at test.cc:47
(lldb)

我认为此错误消息表示足够的信息。


我做了一些修改。使其工作。

除非每个单词简短而唯一,否则我无法想象以前的单词可以工作。

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct listNode {
  int id;
  struct listNode *next;
} ListNode;

typedef struct treeNode {
  char *word;
  char *key;
  int freq;
  ListNode *head;
  struct treeNode *left;
  struct treeNode *right;
} TreeNode;

TreeNode *insertItem(TreeNode *root, char *gword);
void printTreeInorder(TreeNode *v);
void searchforexist(TreeNode *root, char *key);
void freeNodes(TreeNode *root);

#define MAX 25
int main() {
  char word[MAX];
  TreeNode *root = NULL;

  FILE *fp = fopen("input.txt", "r");

  memset(word, 0, MAX);
  if (fp != NULL) {
    // why fsanf("%s \n") ? is this a very special format?
    while (fscanf(fp, "%24s \n", word) != EOF) {
      // fprintf(stderr, "got: [%s]\n", word);
      root = insertItem(root, word);

      if (strcmp(word, "eof") == 0) break;
    }

    fclose(fp);
  }

  printTreeInorder(root);
  printf("\n");

  freeNodes(root);
  return 0;
}

TreeNode *insertItem(TreeNode *root, char *gword) {
  TreeNode *v = root;
  TreeNode *pv = NULL;
  while (v != NULL) {
    pv = v;
    int comp = strcmp(gword, v->word);
    if (comp < 0) {
      v = v->left;
    } else if (comp > 0) {
      v = v->right;
    } else {
      // char *key = v->word;
      char *word = v->word;
      searchforexist(root, word);
      return root;
    }
  }

  TreeNode *tmp = (TreeNode *)malloc(sizeof(TreeNode));
  // why both key and word?
  tmp->word = strdup(gword);
  tmp->left = tmp->right = NULL;
  tmp->freq = 1;

  if (root != NULL) {
    if (strcmp(gword, pv->word) < 0) {
      pv->left = tmp;
    } else {
      pv->right = tmp;
    }
  } else
    root = tmp;

  return root;
}

void searchforexist(TreeNode *root, char *word) {
  if(root == NULL) {
    return;
  }

  int comp = strcmp(word, root->word);

  if(comp == 0) {
    root->freq++;
  } else {
    searchforexist(comp < 0 ? root->left : root->right , word);
  }

}

void printTreeInorder(TreeNode *v) {
    if (v==NULL) return;

    printf("(");
    printTreeInorder(v->left);
    printf(")");

    printf(" %.4s ", v->word);

    printf("(");
    printTreeInorder(v->right);
    printf(")");
}

void freeNodes(TreeNode *root) {
  if (root == NULL) {
    return;
  }
  freeNodes(root->left);
  freeNodes(root->right);

  if(root->word != NULL) free(root->word);
  if(root->key != NULL) free(root->key);
  free(root);
  return;
}