我尝试创建一个包含2个int值的队列。问题发生在插入功能中。当我尝试分配内存时 -> Front->下一个程序停止。该错误仅在插入功能中发生。
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);
}
我在您的代码中看到以下问题:
问题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);
我认为您需要添加其他部分 -
(head->front->next).info=(struct Patient *)malloc(sizeof(struct Patient));
当我尝试将内存分配为HEAD-> FRONT->下一个程序停止时。该错误仅在插入功能中发生。
实际上,如果该错误发生在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
,还可以释放 new 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
s。
但是,另一种可能性是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
来确定队列是否为空,如果在任何元素被征用后排空,则该测试将产生错误的结果。