malloc无法为队列中的struct创建空间

时间:2015-05-08 17:08:24

标签: c struct queue malloc

我尝试创建一个包含2个int值的队列。插入功能发生问题。当我尝试为head-> front->下一个程序停止分配内存时。该错误仅发生在插入函数的else部分。

struct Patient{
   int national_id;
   int condition;
};

struct Node{
   struct Patient *info;
   struct Node *next;
};

struct Queue{
   int total;
   struct Node *rear;
   struct Node *front;
   int insert_number;
};

void insert (struct Queue *head, int natid, int cond);
void pop_min(struct Queue *head);
struct Queue *create_queue(void);
void destroy_queue(struct Queue *head);
void read_file(struct Queue *head);
void print_natid(struct Node *node);
void pop_all_elements(struct Queue *head);

void main(){
   struct Queue *head;

   head=create_queue();
   read_file(head);
   pop_all_elements(head);
   destroy_queue(head);
}

struct Queue *create_queue(void){

   struct Queue *head =(struct Queue*) malloc(sizeof(struct Queue));
   head->total=0;
   head->insert_number=0;
   return head;

}

void print_natid(struct Node *node){
   printf("%d ",node->info->national_id);
}


void insert (struct Queue *head,int natid, int cond){

   if(head->total==0){
      head->front=(struct Node*)malloc(sizeof(struct Node));
      head->front->info->national_id=natid;
      head->front->info->condition=cond;
      head->rear=head->front;
   }
   else{

      head->front->next=(struct Node*)malloc(sizeof(struct Node));
      head->front->next->info->national_id=natid;
      head->front->next->info->condition=cond;
      head->front=head->front->next;
   }


   head->insert_number++;
   head->total++;

   if(head->insert_number==3){
      pop_min(head);
      head->insert_number=0;
   }

   print_natid(head->rear);

}

void pop_min(struct Queue *head){

   printf("%d ",head->rear->info->national_id);

   struct Node *temp=head->rear;
   head->rear=head->rear->next;

   free(head->rear);
   free(temp);
}

void destroy_queue(struct Queue *head){
   free(head);
}

void pop_all_elements(struct Queue *head){
   struct Node *temp;

   while(head->rear!=head->front){
      print_natid(head->rear);
      temp=head->rear;
      free(temp);
      head->rear=head->rear->next;
   }

   print_natid(head->rear);
   free(head->rear);

}

void read_file(struct Queue *head){
   FILE *fp;
   int natid;
   int cond;
   fp=fopen("patients.txt","r");

   while (fscanf(fp,"%d %d", &natid, &cond) ==2)
      insert(head,natid,cond);

   fclose(fp);
}

3 个答案:

答案 0 :(得分:1)

我认为您需要添加else部分 -

(head->front->next).info=(struct Patient *)malloc(sizeof(struct Patient));

答案 1 :(得分:1)

我在您的代码中看到以下问题:

问题1

insert()中,在为其设置值之前,您尚未为新分配的info的{​​{1}}分配内存。

您也没有在Node中设置新构造的节点的nextinsert仍未初始化。如果稍后访问该指针,则会遇到未定义的行为。

我会更改以下代码块来修复上述问题并减少重复代码。

您的代码:

rear->next

我的建议:

if(head->total==0){
   head->front=(struct Node*)malloc(sizeof(struct Node));
   head->front->info->national_id=natid;
   head->front->info->condition=cond;
   head->rear=head->front;
}
else{

   head->front->next=(struct Node*)malloc(sizeof(struct Node));
   head->front->next->info->national_id=natid;
   head->front->next->info->condition=cond;
   head->front=head->front->next;
}

问题2

您在struct Node* node = malloc(sizeof(struct Node)); node->next = NULL; node->info = malloc(sizeof(struct Patient)); node->info->national_id=natid; node->info->condition=cond; if(head->total==0){ head->front = node; head->rear = node; } else{ head->front->next = node; head->front = node; } 中有free的额外电话。

pop_min

问题3

// This is wrong. // Not only do you not need this but also it causes // problems later when you try to use head->rear. free(head->rear); 中的以下行是个问题。

pop_all_elements

您需要交换最后两行。使用:

  temp=head->rear;
  free(temp);

  // PROBLEM
  // Here you are trying to access memory that just got free'd in
  // previous line.
  head->rear=head->rear->next;

答案 2 :(得分:1)

  

当我尝试为head-> front->下一个程序停止分配内存时。该错误仅发生在插入函数的else部分。

如果实际上错误发生在malloc()内,那么它就会出现内存损坏问题的症状,其真正的位置可能在其他地方。一个候选人就是来自pop_all_elements()的错误代码:

while(head->rear!=head->front){
    print_natid(head->rear);
    temp=head->rear;
    free(temp);
    head->rear=head->rear->next;
}

在评估head->rear->next时,它取消引用指向已释放内存的指针。通过将free(temp)移动到循环体的末尾来解决此问题。

另一位候选人是pop_min()

   struct Node *temp=head->rear;
   head->rear=head->rear->next;

   free(head->rear);
   free(temp);

观察您不仅释放旧的rear,还释放新的 rear,让head->rear无效指针(您很可能会尝试如果程序继续过去,那么以后再次免费。该函数有时由insert()调用,因此可能会导致重复调用insert()时遇到问题,例如由函数read_file()执行。

其他候选者包括出现在插入函数的两个分支中的代码:

    head->front->info->national_id=natid;
    head->front->info->condition=cond;

在这两种情况下都没有为head->front->info赋值,因此这两个赋值会产生未定义的行为,这绝对可能表现为内存损坏。您可以考虑通过将Node.info的类型从struct Patient *更改为struct Patient来修复此问题(在其他地方进行相应更改);除此之外,当您使节点出列时,这也可以减轻免费动态分配Patient的需要。

然而,另一种可能性是malloc()工作正常,但head->front是空指针或无效指针,因此分配给head->front->next会产生未定义的行为(表现为内存访问冲突)并伴随停止)。我不太明白会发生什么,但考虑到你有几个与指针有关的问题,可以想象。

虽然我对此表示反对,但我发现你的措施显然旨在将队列限制为两个元素,这些措施严重无效。这段代码......

head->insert_number++;
head->total++;

if(head->insert_number==3){
    pop_min(head);
    head->insert_number=0;
}

...将每三个队列中的一个元素出列队列,但如果四个或更多元素在任何队列之前排队(否则),那么队列将包含两个以上的元素。此外,当您使元素出列时,您不会更新insert_numbertotal,因此这些信息仅包含有关插入了多少元素的信息。请特别注意insert()依赖于total来确定队列是否为空,如果队列在任何元素入队后被清空,则此测试将产生错误的结果。