malloc 无法为队列中的结构创建 space

malloc can't create space for struct in queue

我试图创建一个包含 2 个 int 值的队列。问题发生在插入函数中。当我尝试为 head->front->next 程序暂停分配内存时。该错误仅发生在插入函数的 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);
}

我认为你需要在else部分添加-

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

我在您的代码中发现了以下问题:

问题 1

insert() 中,您尚未为新分配的 Nodeinfo 分配内存,然后再为其设置值。

你也没有在insert中设置新建节点的nextrear->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;
}

我的建议:

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;
}

问题2

您在 pop_min 中还有一个 free 电话。

// 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);

问题3

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;

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

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

When i try to allocate memory for head->front->next program halts. The error happens only in else part in insert function.

如果错误实际上发生在 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 来解决这个问题(在其他地方进行相应的更改);除其他事项外,这还可以减轻您对 free 那些动态分配的 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判断队列是否为空,如果入队后队列为空,则此测试会产生错误结果。