После компиляции 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. В данном случае выводится значение без знака разыменования, что означает, что адрес интерпретируется как смещение от начала блока памяти.