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

标签 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 文件: { 这个测试文件中的单词用于测试目的 将字符串传输到数据结构中。 }

但是,如果我将其更改为这样,我会遇到段错误: { 这个测试文件中的单词用于测试目的 将字符串传输到数据结构中。 & 这个测试文件中的单词用于测试目的 将字符串传输到数据结构中。 }

最佳答案

一个简单的方法是使用 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;
}

关于c - 读取 2kb txt 文件时出现段错误 (c),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54186772/

相关文章:

c - 为什么这个c程序中出现Segmentation failure错误?

javascript - node.js socket.io 脚本在 1-2 天后被 SIGSEGV 杀死

c - 如何定义任意大小的二维数组,然后在编译时确定其维度?

c - SDL_Delay 在与 Emscripten 一起使用时停止渲染?

c# - 段错误 : 11

linux - 根据目录名称移动文件 (Linux/Debian/#!)

php - 有效地计算文本文件的行数。 (200mb+)

c - 为传递给函数的数组指针初始化内存时出现段错误

c - 使用fseek读写文件,读取数据错误

linux - 如何在 Linux 汇编中创建文件