#c #memory-leaks #malloc #dynamic-memory-allocation
Вопрос:
Я запустил автогрейдер в своей программе и получил эту ошибку, но когда я запускаю тот же самый тест вручную, кажется, что он работает нормально. Я не уверен, почему я получаю ошибку только тогда, когда использую автогрейдер. Я новичок в C, и я не понимаю, почему происходит утечка памяти, потому что я освободил все переменные, для которых я использовал malloc. Это показывает мне, какие строки конкретно вызывают ошибку, но я не знаю, как ее исправить, не «испортив» мой код/вывод.
Исходный код:
struct Node* head; //global variable
void Insert(int x){
struct Node* temp = (struct Node*)malloc(sizeof(struct Node));
struct Node* ptr = head;
//check if already present
while(ptr != NULL){
if(ptr->data == x){return;}
ptr = ptr->next;
}
//check if head is greater
if(head == NULL || head->data > x){
temp->data = x;
temp->next = head;
head = temp;
}else{
ptr = head;
while(ptr->next != NULL amp;amp; ptr->next->data < x){
ptr = ptr->next;
}
temp->data = x;
temp->next = ptr->next;
ptr->next = temp;
}
}
void Delete(int x){
struct Node* temp = head;
struct Node* prev;
//if head has key
if(temp != NULL amp;amp; temp->data == x){
head = temp->next;
free(temp);
return;
}
//find key
while(temp != NULL amp;amp; temp->data != x){
prev=temp;
temp = temp->next;
}
//if key isnt present
if(temp == NULL){return;}
//unlink
prev->next = temp->next;
free(temp);
}
void Print(){
struct Node* temp = head;
int c = 0;
while(temp != NULL){
c ;
temp = temp->next;
}
printf("%d :", c);
temp = head;
while(temp != NULL){
printf(" %d", temp->data);
temp = temp->next;
}
printf("n");
}
int main(){
int x;
char c;
head = NULL; //empty list
scanf(" %c%d",amp;c,amp;x);
if(c == 'i'){
Insert(x);
}else if(c == 'd'){
Delete(x);
}
Print();
while(scanf(" %c%d",amp;c,amp;x)!=EOF){
if(c == 'i'){
Insert(x);
}else if(c == 'd'){
Delete(x);
}
Print();
}
return 0;
}
Комментарии:
1. Вы допустите утечку переменной temp, когда ptr->данные будут равны x внутри функции вставки. Вы просто возвращаетесь, не освобождая его.
Ответ №1:
Ваша проблема здесь
void Insert(int x){
struct Node* temp = (struct Node*)malloc(sizeof(struct Node));
struct Node* ptr = head;
//check if already present
while(ptr != NULL){
if(ptr->data == x){return;} <--- If this return is executed, temp is not freed
ptr = ptr->next;
}
Чтобы исправить это, просто переместите malloc
его так, чтобы он был после цикла.
void Insert(int x){
struct Node* ptr = head;
//check if already present
while(ptr != NULL){
if(ptr->data == x){return;}
ptr = ptr->next;
}
struct Node* temp = malloc(sizeof(struct Node));
кстати:
- Иметь
head
в качестве глобальной переменной плохую идею - Не приводите значение, возвращаемое
malloc
Комментарии:
1. Вы не знаете контекста переменной head, поэтому не знаете, плохая это идея или нет. Вам следует удалить это замечание.
2. @Fredrik нет, нет, нет….
head
как глобальная переменная плоха в любом контексте3. @4386472 удачи в попытке написать код прерывания без глобальных переменных. Или любой встроенный код, если на то пошло. Люди кричат о стигматизации глобальной переменной только потому, что они где-то читали, что это было плохо.
4. @Fredrik Есть случаи, когда необходимы глобальные переменные, но здесь это абсолютно неправильно
5. @Fredrik, ограничив использование всех функций одним связанным списком.