После компиляции VS2008 падает после удаления узла дерева, имеющего потомка - C (СИ)

Узнай цену своей работы

Формулировка задачи:

Вот код на Си:
Листинг программы
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <malloc.h>
  4. #include <conio.h>
  5. struct Node;
  6. struct ChildNode{
  7. struct ChildNode *prev;
  8. struct ChildNode *next;
  9. struct Node *element;
  10. };
  11. typedef struct ChildNode childnode;
  12. struct Node{
  13. int index;
  14. double value;
  15. childnode *parent;
  16. childnode *children;
  17. };
  18. typedef struct Node node;
  19. struct List{
  20. int count;
  21. struct List *prev;
  22. };
  23. typedef struct List list;
  24. node *first;
  25. int count = 0;
  26. node *GetElementByIndex(int index, node *t)
  27. {
  28. node *temp = NULL;
  29. childnode *c;
  30. if (t==NULL)
  31. return NULL;
  32. if (t->index==index)
  33. return t;
  34. c=t->children->next;
  35. if (c==NULL)
  36. return NULL;
  37. while (c!=NULL)
  38. {
  39. temp=GetElementByIndex(index,c->element);
  40. if (temp!=NULL)
  41. break;
  42. c=c->next;
  43. }
  44. if (temp!=NULL)
  45. return temp;
  46. return NULL;
  47. }
  48. int AddNode(int index, double value)
  49. {
  50. node *t, *temp;
  51. childnode *c, *child;
  52. if (first==NULL)
  53. {
  54. temp = (node *)malloc(sizeof(node));
  55. temp->value = value;
  56. temp->index = 1;
  57. temp->children = (childnode*)malloc(sizeof(childnode));
  58. temp->children->prev = NULL;
  59. temp->children->next = NULL;
  60. temp->children->element = NULL;
  61. first=temp;
  62. count=1;
  63. return 0;
  64. }
  65. t = GetElementByIndex(index,first);
  66. if (t==NULL)
  67. return -1;
  68. ++count;
  69. temp = (node *)malloc(sizeof(node));
  70. child = (childnode*)malloc(sizeof(child));
  71. temp->value = value;
  72. temp->index = count;
  73. temp->parent = child;
  74. temp->children = (childnode*)malloc(sizeof(childnode));
  75. temp->children->prev = NULL;
  76. temp->children->next = NULL;
  77. temp->children->element = NULL;
  78. child->next = NULL;
  79. child->element = temp;
  80. c=t->children;
  81. while (c->next!=NULL)
  82. c=c->next;
  83. child->prev = c;
  84. c->next = child;
  85. return 0;
  86. }
  87. void PrintTree(const char *str, node *p)
  88. {
  89. childnode *c;
  90. char temp[50];
  91. if (p==NULL)
  92. return;
  93. printf("%s%i: %0.2f\n",str,p->index,p->value);
  94. if (p->children->next==NULL)
  95. return;
  96. strcpy(temp,str);
  97. strcat(temp,"\t\0");
  98. c=p->children->next;
  99. while (c!=NULL)
  100. {
  101. PrintTree(temp,c->element);
  102. c=c->next;
  103. }
  104. return;
  105. }
  106. void DeleteTree(node *p)
  107. {
  108. childnode *c, *cTemp;
  109. c=p->children->next;
  110. while (c!=NULL)
  111. {
  112. DeleteTree(c->element);
  113. cTemp = c;
  114. c = c->next;
  115. free(cTemp); //Падает тут
  116. cTemp = NULL;
  117. }
  118. free(p->children);
  119. if (first==p)
  120. first = NULL;
  121. else
  122. {
  123. if (p->parent->next!=NULL)
  124. p->parent->next->prev = p->parent->prev;
  125. p->parent->prev->next = p->parent->next;
  126. }
  127. p->parent->element=NULL;
  128. free(p);
  129. }
  130. void Delete(int index)
  131. {
  132. node *t;
  133. if (first==NULL)
  134. return;
  135. t = GetElementByIndex(index,first);
  136. if (t==NULL)
  137. return;
  138. DeleteTree(t);
  139. return;
  140. }
  141. int main()
  142. {
  143. char c;
  144. int index, cnt;
  145. double value;
  146. do
  147. {
  148. c = getch();
  149. switch(c)
  150. {
  151. case '1':
  152. PrintTree("", first); break;
  153. case '2':
  154. printf("Input index and value to input: "); scanf("%i%le",&index,&value); AddNode(index,value); break;
  155. case '3':
  156. printf("Input index to delete"); scanf("%i",&index); Delete(index); break;
  157. }
  158. } while (c!='4');
  159. }
программа строит дерево, печатает его, удаляет узлы (с удалением всех дочерних узлов). в борладне все работает. Под *nix системами после компиляции gcc и в win после компиляции VS2008 падает после удаления узла дерева, имеющего потомка. Не могу разобраться почему, вроде все корректно выделяю, да и free передаю тот же адрес, что выделил мне malloc. Помогите разобраться, пожалуйста. Выделю место, где программа падает, на всякий:
Листинг программы
  1. c=p->children->next;
  2. while (c!=NULL)
  3. {
  4. DeleteTree(c->element);
  5. cTemp = c;
  6. c = c->next;
  7. free(cTemp); //Падает тут
  8. cTemp = NULL;
  9. }

Решение задачи: «После компиляции VS2008 падает после удаления узла дерева, имеющего потомка»

textual
Листинг программы
  1. p = malloc (....);
  2. printf ("malloc res=%p\n", p);
  3. printf ("res[-1]=0x%08x\n", *(((int*)p)-1));
  4. printf ("res[-2]=0x%08x\n", *(((int*)p)-2));

Объяснение кода листинга программы

  1. p = malloc (....); - здесь происходит выделение памяти динамическим способом при помощи функции malloc. В точке вызова функции malloc передается некий аргумент, который определяет размер выделяемой памяти. Точный размер памяти не указан в вопросе, поэтому в описании кода этот аргумент не приводится.
  2. printf (malloc res=%p\n, p); - здесь выполняется вывод информации о выделенной памяти. Форматированный вывод осуществляется при помощи функции printf. Передается строка формата malloc res=%p и указатель на выделенную память p. Результатом выполнения этого фрагмента кода будет строка, в которой будет указано место выделения памяти.
  3. printf (res[-1]=0x%08x\n, *(((int*)p)-1)); - здесь выполняется доступ к значению, находящемуся по адресу p - 1, который интерпретируется как целое число. Поскольку указатель p указывает на начало блока памяти, то выражение p - 1 будет указывать на последний элемент этого блока. Затем происходит форматированный вывод значения этого элемента при помощи функции printf. В данном случае выводится значение без знака разыменования, что означает, что адрес интерпретируется как смещение от начала блока памяти.
  4. printf (res[-2]=0x%08x\n, *(((int*)p)-2)); - здесь выполняется доступ к значению, находящемуся по адресу p - 2, который интерпретируется как целое число. Затем происходит форматированный вывод значения этого элемента при помощи функции printf. В данном случае выводится значение без знака разыменования, что означает, что адрес интерпретируется как смещение от начала блока памяти.

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

7   голосов , оценка 4.286 из 5

Нужна аналогичная работа?

Оформи быстрый заказ и узнай стоимость

Бесплатно
Оформите заказ и авторы начнут откликаться уже через 10 минут
Похожие ответы