【问题标题】:malloc can't create space for struct in queuemalloc 无法为队列中的结构创建空间
【发布时间】:2015-05-08 17:08:23
【问题描述】:

我尝试创建一个包含 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);
}

【问题讨论】:

  • total 究竟代表什么?
  • 元素总数。
  • 所以你不断地将新元素连接到同一个头部。您应该要么添加到队列的最后一个元素,而不是头部,要么从头部开始遍历列表。
  • 我从 head->front 添加元素。后总是保存队列中最旧的元素。头是一次创建的。其实我没明白我的意思。
  • 你在同一个地方一遍又一遍地添加元素。分析你的代码在做什么。

标签: c struct queue malloc


【解决方案1】:

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

问题 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);

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • 这两个部分实际上都缺失了,而且您在 then else 部分中创建了一个循环。
    • 我添加了那部分但没有帮助。因为它不为 head->front->next 分配内存,所以问题从那里开始。同样在 Node struct 中也有一个 struct Patient 的指针。如果我为节点分配内存,我猜会自动为患者创建空间。
    • 正如 chqrlie 所说的 if 部分也缺少它,您的内存分配不正确。您必须以相同的方式分配内存@Y.E.S.
    • head->front->next 没有被创建。如果我能够创建 head->front->next,我会尝试你所说的。但主要问题是关于 head->fron->next 的内存分配,它给出了错误。
    • 如果你创建一个像struct node *temp这样的临时节点,然后将所有值分配给temp,你将它添加到你喜欢的后面或前面会更好。这将降低您的复杂性@Y.E.S.
    【解决方案3】:

    当我尝试为 head->front->next 分配内存时,程序会停止。该错误仅发生在插入函数的 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 来解决此问题(在其他地方进行相应的更改);除其他外,当您将节点出列时,这也将免除您释放那些动态分配的Patients 的任何需要。

    然而,另一种可能性是 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判断队列是否为空,如果队列在任何元素入队后被清空,此测试将产生错误结果。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-02-15
      • 2023-03-10
      • 2021-11-22
      • 2015-01-05
      • 2023-03-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多