我尝试创建一个包含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);
}
答案 0 :(得分:1)
我认为您需要添加else部分 -
(head->front->next).info=(struct Patient *)malloc(sizeof(struct Patient));
答案 1 :(得分:1)
我在您的代码中看到以下问题:
问题1
在insert()
中,在为其设置值之前,您尚未为新分配的info
的{{1}}分配内存。
您也没有在Node
中设置新构造的节点的next
。 insert
仍未初始化。如果稍后访问该指针,则会遇到未定义的行为。
我会更改以下代码块来修复上述问题并减少重复代码。
您的代码:
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_number
或total
,因此这些信息仅包含有关插入了多少元素的信息。请特别注意insert()
依赖于total
来确定队列是否为空,如果队列在任何元素入队后被清空,则此测试将产生错误的结果。