После компиляции VS2008 падает после удаления узла дерева, имеющего потомка - C (СИ)
Формулировка задачи:
Вот код на Си:
программа строит дерево, печатает его, удаляет узлы (с удалением всех дочерних узлов).
в борладне все работает. Под *nix системами после компиляции gcc и в win после компиляции VS2008 падает после удаления узла дерева, имеющего потомка. Не могу разобраться почему, вроде все корректно выделяю, да и free передаю тот же адрес, что выделил мне malloc. Помогите разобраться, пожалуйста.
Выделю место, где программа падает, на всякий:
#include <stdio.h> #include <string.h> #include <malloc.h> #include <conio.h> struct Node; struct ChildNode{ struct ChildNode *prev; struct ChildNode *next; struct Node *element; }; typedef struct ChildNode childnode; struct Node{ int index; double value; childnode *parent; childnode *children; }; typedef struct Node node; struct List{ int count; struct List *prev; }; typedef struct List list; node *first; int count = 0; node *GetElementByIndex(int index, node *t) { node *temp = NULL; childnode *c; if (t==NULL) return NULL; if (t->index==index) return t; c=t->children->next; if (c==NULL) return NULL; while (c!=NULL) { temp=GetElementByIndex(index,c->element); if (temp!=NULL) break; c=c->next; } if (temp!=NULL) return temp; return NULL; } int AddNode(int index, double value) { node *t, *temp; childnode *c, *child; if (first==NULL) { temp = (node *)malloc(sizeof(node)); temp->value = value; temp->index = 1; temp->children = (childnode*)malloc(sizeof(childnode)); temp->children->prev = NULL; temp->children->next = NULL; temp->children->element = NULL; first=temp; count=1; return 0; } t = GetElementByIndex(index,first); if (t==NULL) return -1; ++count; temp = (node *)malloc(sizeof(node)); child = (childnode*)malloc(sizeof(child)); temp->value = value; temp->index = count; temp->parent = child; temp->children = (childnode*)malloc(sizeof(childnode)); temp->children->prev = NULL; temp->children->next = NULL; temp->children->element = NULL; child->next = NULL; child->element = temp; c=t->children; while (c->next!=NULL) c=c->next; child->prev = c; c->next = child; return 0; } void PrintTree(const char *str, node *p) { childnode *c; char temp[50]; if (p==NULL) return; printf("%s%i: %0.2f\n",str,p->index,p->value); if (p->children->next==NULL) return; strcpy(temp,str); strcat(temp,"\t\0"); c=p->children->next; while (c!=NULL) { PrintTree(temp,c->element); c=c->next; } return; } void DeleteTree(node *p) { childnode *c, *cTemp; c=p->children->next; while (c!=NULL) { DeleteTree(c->element); cTemp = c; c = c->next; free(cTemp); //Падает тут cTemp = NULL; } free(p->children); if (first==p) first = NULL; else { if (p->parent->next!=NULL) p->parent->next->prev = p->parent->prev; p->parent->prev->next = p->parent->next; } p->parent->element=NULL; free(p); } void Delete(int index) { node *t; if (first==NULL) return; t = GetElementByIndex(index,first); if (t==NULL) return; DeleteTree(t); return; } int main() { char c; int index, cnt; double value; do { c = getch(); switch(c) { case '1': PrintTree("", first); break; case '2': printf("Input index and value to input: "); scanf("%i%le",&index,&value); AddNode(index,value); break; case '3': printf("Input index to delete"); scanf("%i",&index); Delete(index); break; } } while (c!='4'); }
c=p->children->next; while (c!=NULL) { DeleteTree(c->element); cTemp = c; c = c->next; free(cTemp); //Падает тут cTemp = NULL; }
Решение задачи: «После компиляции VS2008 падает после удаления узла дерева, имеющего потомка»
textual
Листинг программы
p = malloc (....); printf ("malloc res=%p\n", p); printf ("res[-1]=0x%08x\n", *(((int*)p)-1)); printf ("res[-2]=0x%08x\n", *(((int*)p)-2));
Объяснение кода листинга программы
p = malloc (....);
- здесь происходит выделение памяти динамическим способом при помощи функцииmalloc
. В точке вызова функцииmalloc
передается некий аргумент, который определяет размер выделяемой памяти. Точный размер памяти не указан в вопросе, поэтому в описании кода этот аргумент не приводится.printf (
malloc res=%p\n, p);
- здесь выполняется вывод информации о выделенной памяти. Форматированный вывод осуществляется при помощи функцииprintf
. Передается строка форматаmalloc res=%p
и указатель на выделенную памятьp
. Результатом выполнения этого фрагмента кода будет строка, в которой будет указано место выделения памяти.printf (
res[-1]=0x%08x\n, *(((int*)p)-1));
- здесь выполняется доступ к значению, находящемуся по адресуp - 1
, который интерпретируется как целое число. Поскольку указательp
указывает на начало блока памяти, то выражениеp - 1
будет указывать на последний элемент этого блока. Затем происходит форматированный вывод значения этого элемента при помощи функцииprintf
. В данном случае выводится значение без знака разыменования, что означает, что адрес интерпретируется как смещение от начала блока памяти.printf (
res[-2]=0x%08x\n, *(((int*)p)-2));
- здесь выполняется доступ к значению, находящемуся по адресуp - 2
, который интерпретируется как целое число. Затем происходит форматированный вывод значения этого элемента при помощи функцииprintf
. В данном случае выводится значение без знака разыменования, что означает, что адрес интерпретируется как смещение от начала блока памяти.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д