C语言 Segfault:跟踪字符串中唯一字符的频率并存储在数组中

xwbd5t1u  于 2023-03-11  发布在  其他
关注(0)|答案(3)|浏览(107)

我还有另一个C问题,这次我尝试计算每个字符在给定字符串中的出现频率,每个唯一的字符将存储在一个节点结构中,并添加到一个节点结构数组中,以便稍后在霍夫曼编码实现中使用(堆/二叉树已经构建,只是在这些频率方面遇到了问题)。
这是我的代码:

typedef struct node {

  unsigned int freq;
  char character;
  struct node *left, *right;

} node;

//constructor for node struct
node* Node (char c, node* left, node* right){
  
  node* myNode = malloc(sizeof(node));

  myNode->freq = 0;
  myNode->character = c;
  myNode->left = left;
  myNode->right = right;

  return myNode;

}

node** storeFreq = malloc(sizeof(node) * 256);
  
  char c;
    int totalNumOfCharacters = 0;

    //read the file character by character
    while ((c = fgetc(inputFile)) != EOF && c != '\n')
    {
      printf("%c\n", c);

      if (totalNumOfCharacters == 0) {
          
          //make the node
          node* myNode = Node(c, NULL, NULL);

          //put it in the list
          storeFreq[0] = myNode;

          //increase the frequency of the character by one
              storeFreq[0]->freq++;

              //increase the total character count
              totalNumOfCharacters++;

        }

      else {

      for (int i = 0; i < totalNumOfCharacters; i++){

        //if the character is already in the table
        if (storeFreq[i]->character == c){

          //increase the frequency of the character by one
              storeFreq[i]->freq++;

        }
        
        //if it's not in the table
        else {

          //make the node
          node* myNode = Node(c, NULL, NULL);

          //put it in the list
          storeFreq[totalNumOfCharacters - 1] = myNode;

          //increase the frequency of the character by one
              storeFreq[i]->freq++;

              //increase the total character count
              totalNumOfCharacters++;

        }
        }
      }

    }

    fclose(inputFile);

//print frequencies
    int i = 0;
    while (i < totalNumOfCharacters) {
      printf("i: %d", i);
      printf("Character: %c | Frequency: %d\n", storeFreq[i]->character, storeFreq[i]->freq);
      i++;
    }

以下是valgrind输出:

==292846== Memcheck, a memory error detector
==292846== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==292846== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==292846== Command: ./a.out encode message.txt message_codeTable.txt
==292846== 
T
h
==292846== Use of uninitialised value of size 8
==292846==    at 0x1095F4: main (file.c:181)
==292846== 
==292846== Invalid read of size 1
==292846==    at 0x1095F4: main (file.c:181)
==292846==  Address 0x4 is not stack'd, malloc'd or (recently) free'd
==292846== 
==292846== 
==292846== Process terminating with default action of signal 11 (SIGSEGV)
==292846==  Access not within mapped region at address 0x4
==292846==    at 0x1095F4: main (file.c:181)
==292846==  If you believe this happened as a result of a stack
==292846==  overflow in your program's main thread (unlikely but
==292846==  possible), you can try to increase the size of the
==292846==  main thread stack using the --main-stacksize= flag.
==292846==  The main thread stack size used in this run was 8388608.
==292846== 
==292846== HEAP SUMMARY:
==292846==     in use at exit: 15,880 bytes in 6 blocks
==292846==   total heap usage: 6 allocs, 0 frees, 15,880 bytes allocated
==292846== 
==292846== LEAK SUMMARY:
==292846==    definitely lost: 0 bytes in 0 blocks
==292846==    indirectly lost: 0 bytes in 0 blocks
==292846==      possibly lost: 0 bytes in 0 blocks
==292846==    still reachable: 15,880 bytes in 6 blocks
==292846==         suppressed: 0 bytes in 0 blocks
==292846== Reachable blocks (those to which a pointer was found) are not shown.
==292846== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==292846== 
==292846== Use --track-origins=yes to see where uninitialised values come from
==292846== For lists of detected and suppressed errors, rerun with: -s
==292846== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
Segmentation fault (core dumped)

我如何跟踪这个分段错误?我需要一个健全的检查。

gz5pxeao

gz5pxeao1#

检查以下行:

==292846==   total heap usage: 6 allocs, 0 frees, 15,880 bytes allocated

对于像malloc这样的每一次内存分配,都应该释放已经分配的内存字节,以便编译器可以使用这些字节。
如果你举个例子:

node* myNode = malloc(sizeof(node));

在程序完成之前,应该执行free(node),这样就不会发生内存泄漏
对于分段错误,您可能试图访问一些无效的内存地址,我还建议使用调试器,因为它在这种情况下确实很有帮助

b5lpy0ml

b5lpy0ml2#

我想出来了,应该加到totalNum而不是totalNum - 1。

zf9nrax1

zf9nrax13#

此处:

//increase the frequency of the character by one
      storeFreq[i]->freq++;

你使用i作为索引,它已经运行到数组的末尾,你的意思是:

//increase the frequency of the character by one
          storeFreq[totalNumCharacters - 1]->freq++;

相关问题