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()
中,您尚未为新分配的 Node
的 info
分配内存,然后再为其设置值。
你也没有在insert
中设置新建节点的next
。 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;
}
我的建议:
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_number
或 total
,因此这些信息仅包含有关曾经插入了多少元素的信息。特别注意,insert()
依赖total
判断队列是否为空,如果入队后队列为空,则此测试会产生错误结果。
我试图创建一个包含 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()
中,您尚未为新分配的 Node
的 info
分配内存,然后再为其设置值。
你也没有在insert
中设置新建节点的next
。 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;
}
我的建议:
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_number
或 total
,因此这些信息仅包含有关曾经插入了多少元素的信息。特别注意,insert()
依赖total
判断队列是否为空,如果入队后队列为空,则此测试会产生错误结果。