在 while 循环中重用已释放的链表时出现问题

问题描述 投票:0回答:1

当我运行代码时,只有外循环的第一次迭代给出了有意义的输出。输出总数是正确的,但除第一个输出之外的所有其余输出都打印“-”,这意味着“findWord”输出 NULL。假设正确包含所需的所有头文件,我该如何解决这个问题?

我有一个链表实现为:

typedef struct Node{
    char* word;
    int freq;
    struct Node *next;
}Node;

typedef struct {
    Node* head;

}LL;

LL* createLL(){
  LL* list = malloc(sizeof(LL));
  if (list) {
    list->head = NULL;
  }
  return list;
}

并使用以下方法释放:

void destroyLL(LL* list){
  
  if(list == NULL || list -> head == NULL){
    return;
  }

  Node* current = list->head;
  Node* next;

  while(current != NULL){
    next = current->next;
    free(current->word);
    free(current);
    current = next; 
  }
  list->head = NULL;
  free(list);
}

我将节点添加到列表中的方式是:

void add_Node(LL* list, char* word, int freq){
  Node* newNode = (Node*)malloc(sizeof(Node));
  /*
  if(newNode == NULL){
    fprintf(stderr, "not able to create node\n");
    return;
  }
  */
  newNode->word = strdup(word);
  /*
  if(newNode->word == NULL){
    fprintf(stderr, "can't allocate mem for word\n");
    free(newNode);
    return;
  }
  */
  newNode -> freq = freq;
  newNode->next = NULL;

  if(list->head == NULL){
    list -> head = newNode;
  }
  else{
    Node* current = list->head;
    while(current->next != NULL){
      current = current->next;
    }
    current->next = newNode;
  }
  //return newNode;
}

void addFreq(LL* list, char* word){
  /*
  if(word == NULL){
    return;
  }
  */
  Node* current = list->head;
  while(current != NULL){
    if(strcmp(current->word, word) == 0){
      current->freq++;
      return;
    }

    current = current->next;
  }
  add_Node(list, word, 1);
}

我的主要功能如下:

int main(int argc, char *argv[]){
    FILE* input;

  //LL* list = (LL*)malloc(sizeof(LL));
  //list->head = NULL;  

    char *shake = /*...*/ //the name of a file  
    FILE* shake_txt = fopen(shake, "r");
    input = fopen(argv[1], "r");
  
  char target[100];
  int length;
  int target_freq;
  
  

  while(fgets(target, sizeof(target), input) != NULL){   //gets imputs from a file with inputs on each line
    //LL* list = (LL*)malloc(sizeof(LL));
    //list->head = NULL;
    LL* list = createLL();

    if(sscanf(target, "%d %d", &length, &target_freq)==2){
      
      char word[100];
        while(fgets(word, sizeof(word), shake_txt) != NULL){ //shake_txt has a word on each line, this loop goes through each line and adds the word to the linked list if it is the input length
          if(strlen(word) == length+1){
          addFreq(list, word);
        }
      }
      sortLL(list); //assume nothing goes wrong here

      findWord(list, target_freq)==NULL? printf("-\n"):  printf("%s", findWord(list, target_freq)); finds the target_freq-th node and returns the word
      
      if(findWord(list, target_freq)==NULL){ //this is used for debugging, ignore it
        printLL(list);
      }
      
    }
    destroyLL(list); //frees the linked list so it can be used in the next iteration

  }
  //assume all files are closed properly
}

经过一些测试,我发现在外循环的第一次迭代之后,链表本身没有任何内容。 'addFreq' 有效,

destroyLL
也有效。这是我运行 valgrind 后得到的结果(如果有帮助的话):

==165== Memcheck, a memory error detector
==165== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==165== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==165== Command: ./Bard simple-input.txt
==165== 
father
-
-
-   //<-- only the last line should be a "-" others should be words i.e."father"
-
-
==165== 
==165== HEAP SUMMARY:
==165==     in use at exit: 0 bytes in 0 blocks
==165==   total heap usage: 9,705 allocs, 9,705 frees, 165,472 bytes allocated
==165== 
==165== All heap blocks were freed -- no leaks are possible
==165== 
==165== For counts of detected and suppressed errors, rerun with: -v
==165== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
c memory while-loop linked-list
1个回答
0
投票

该问题与您的链接列表无关。就是在外循环的第一次迭代中,您将文件

shake_txt
一直读取到末尾,之后就没有任何内容可供后续迭代读取。

您必须先

rewind(shake_txt)
fseek(shake_txt, 0, SEEK_SET)
才能再次浏览该文件。

© www.soinside.com 2019 - 2024. All rights reserved.