使用链表的斐波那契数列在链表被销毁后崩溃.如何跟踪错误?

  • 本文关键字:链表 何跟踪 崩溃 跟踪 错误 数列 c
  • 更新时间 :
  • 英文 :


我正在开发一个程序,该程序可以在不使用 int 数据类型的情况下计算斐波那契数列中的任何数字,因为它会溢出。相反,我使用链表来保存代表每个数字的数字。我目前的问题是释放分配给我不再需要的链表的内存。如果我正在计算 F(10000(,我希望释放以前的数千个列表。程序按原样生成每个值,最高可达"F(7( = 13",然后崩溃并显示"退出状态-1"。我真的只是想知道导致此错误的原因,然后从那里开始。任何帮助,不胜感激。谢谢你,对于大量的代码,我

深表歉意。
#include <stdio.h>
#include <stdlib.h>
typedef struct Node
{
int digit;
struct Node *next;
} Node;
typedef struct ListyInt
{
Node *head;
int length;
} ListyInt;

Node *create_node(unsigned int digit, ListyInt *listy);
Node *removeNode(Node *node, ListyInt *listy);
void listyPrintHelper(Node *current);
ListyInt *destroyListyInt(ListyInt *listy);
ListyInt *fib(unsigned int n);

void listyPrint(ListyInt *p)
{
if (p == NULL || p->head == NULL)
{
printf("(null pointer)n");
return;
}
listyPrintHelper(p->head);
printf("n");
}
void listyPrintHelper(Node *current)
{
if (current == NULL)
return;
listyPrintHelper(current->next);
printf("%d", current->digit);
}
int main()
{
int i;
ListyInt *p;
for (i = 0; i <= 1000; i++)
{
printf("F(%d) = ", i);
listyPrint(p = fib(i));
destroyListyInt(p);
}
return 0;
}
ListyInt *listyAdd(ListyInt *p, ListyInt *q)
{
ListyInt *listy = NULL;
Node *ptemp = NULL;
Node *qtemp = NULL;
Node *temp = NULL;
ListyInt *temp_list = NULL;
unsigned int x = 0;
unsigned int count = 0;
if (p == NULL || q == NULL)
{
return NULL;
}
listy = malloc(sizeof(ListyInt));
if (listy == NULL)
{
return NULL;
}
listy->length = 0;
if (q->length > p->length)
{
temp_list = q;
q = p;
p = temp_list;
}
while (count < p->length)
{
if (count == 0)
{
x = p->head->digit + q->head->digit;
ptemp = p->head->next;
qtemp = q->head->next;
listy->head = create_node(x, listy);
temp = listy->head;
temp->next = create_node(0, listy);
if (temp->digit > 9)
{
temp->digit = temp->digit - 10;
temp->next->digit = temp->next->digit + 1;
}
}
else
{
temp->next->next = create_node(0, listy);
if (qtemp == NULL)
{
temp->next->digit += ptemp->digit;
ptemp = ptemp->next;
temp = temp->next;
}
else
{
x = ptemp->digit + qtemp->digit;
temp->next->digit += x;
if (temp->next->digit > 9)
{
temp->next->digit = temp->next->digit - 10;
temp->next->next->digit = temp->next->next->digit + 1;
}
qtemp = qtemp->next;
ptemp = ptemp->next;
temp = temp->next;
}
}
if (count == p->length - 1 && temp->next->digit == 0)
{
temp->next = removeNode(temp->next, listy);
}
count++;
}
return listy;
}
ListyInt *destroyListyInt(ListyInt *listy)
{
if (listy == NULL)
{
return NULL;
}
Node *current = listy->head;
Node *temp;
while (current != NULL)
{
temp = current->next;
free(current);
current = temp;
}
free(listy);
return NULL;
}
ListyInt *fib(unsigned int n)
{
ListyInt *spiral = malloc(sizeof(ListyInt));
ListyInt *p = NULL;
ListyInt *q = NULL;
unsigned int count = 2;
if (spiral == NULL)
{
return NULL;
}
if (n == 0)
{
spiral->head = create_node(0, spiral);
return spiral;
}
if (n == 1)
{
spiral->head = create_node(1, spiral);
return spiral;
}
p = malloc(sizeof(ListyInt));
p->head = create_node(0, p);
q = malloc(sizeof(ListyInt));
q->head = create_node(1, q);
while (count <= n)
{
spiral = listyAdd(p, q);
destroyListyInt(p);
p = q;
q = spiral;
count++;
}
return spiral;
}
Node *create_node(unsigned int digit, ListyInt *listy)
{
if (listy == NULL)
{
return NULL;
}
Node *new_node = malloc(sizeof(Node));
new_node->digit = digit;
new_node->next = NULL;
listy->length++;
return new_node;
}
Node *removeNode(Node *node, ListyInt *listy)
{
if (node == NULL)
{
return NULL;
}
if (listy == NULL)
{
return NULL;
}
free(node);
node = NULL;
listy->length--;
return NULL;
}

我真的只是想知道是什么导致了这个错误,然后从那里开始。

长话短说,据我所知,C 相当于一个NullPointerException

长话短说,我没有时间完全检查您的代码或调试它,但我有时间通过大多数 Linux 安装中包含的gdb运行它。如果你使用的是Visual Studio,我依稀记得有一个调试模式,它应该向你显示大致相同的信息,只是在不同的位置。这是 GDB 的输出:

Starting program: /home/ubuntu/C/a.out 
F(0) = 0
F(1) = 1
F(2) = 1
F(3) = 2
F(4) = 3
F(5) = 5
F(6) = 8
F(7) = 13
Program received signal SIGSEGV, Segmentation fault.
0x00000000004008db in listyAdd (p=0x6036a0, q=0x6036e0) at main.c:117
117         temp->next->digit += ptemp->digit;

(好吧,这还不是全部,但这是相关的部分。

最后三行的意思是你得到了一个段错误。有很多事情可能会导致它,但基于该行,它看起来像是由尝试取消引用无效指针引起的。这要么是NULL指针(值0x0(,要么是你已经freed 的指针。

如果你使用的是Linux,你可以在上面运行Valgrind,弄清楚到底发生了什么。它会告诉你它是使用freed 指针还是NULL指针,这将为您提供找到实际错误的良好起点。您还可以使用 IDE 的调试器(或 GDB,如果您想尝试使用命令行版本,但我不建议这样做(来单步执行程序并查看所涉及的变量的值是什么,您可以从中向后移动以查看它们被更改和失效的位置。

不过,如果我不得不猜测,我会说0andriy的评论击中了它的鼻子 - 你似乎释放了两次东西,你可能打算在最后释放它们一次。

我有点故意模糊不清。隔离错误很常见,而且(正如你已经注意到的(很难调试,你只能通过经验来真正学习。我认为老实说,向答案展示答案不如自己完成它有用,并且使用 Valgrind 和调试器等工具,这实际上并不难,只是乏味。

我发现了这个问题。这是因为当调用 fib(( 时,我的链表的长度没有被重置。谢谢大家的帮助。

最新更新