我正在开发一个程序,该程序可以在不使用int数据类型的情况下计算斐波那契数列中的任何数字,因为它会溢出。相反,我使用链接列表来保存代表每个数字的数字。我当前的问题是释放分配给不再需要的链表的内存。如果要计算F(10000),则希望释放成千上万个以前的列表。程序按原样生成每个值,直到崩溃并显示“退出状态-1”,直到“ F(7)= 13”。我真的很想知道是什么导致此错误,然后从那里继续。任何帮助表示赞赏。谢谢您,我为其中的大量代码表示歉意。
#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;
}
答案 0 :(得分:4)
我真的很想知道导致此错误的原因并从那里去。
长话短说,据我所知,C相当于NullPointerException
。
长话大说,我还没有时间充分检查您的代码或对其进行调试,但是我有时间通过gdb
(大多数Linux安装中都包含)运行它。如果您使用的是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;
(好的,这还不是全部,但这是相关的。)
最后三行表示您得到了segfault。有很多原因可以导致它,但是基于该行,它似乎是由于尝试取消引用无效指针而引起的。要么是NULL
指针(值为0x0
),要么是您已经free
d指向的指针。
如果您使用的是Linux,则可以在其上运行Valgrind来确定发生了什么。它会告诉您是使用free
d指针还是NULL
指针,这将为您找到实际的错误提供一个很好的起点。您还可以使用IDE的调试器(或GDB,如果您想尝试使用命令行版本,但我不建议这样做)来逐步执行程序,并查看所涉及变量的值是什么,可以向后走,看看它们在哪里被更改和失效了。
但是,如果我不得不猜测的话,我会说0andriy的评论hit之以鼻-您似乎要释放两次,最后可能要释放一次。
我有点故意离开这个模糊的地方。段故障很常见,并且(如您所注意到的)很难调试,您只能通过经验真正地学习如何操作。我认为,显示答案实际上不会比自己亲自解决问题有用,并且使用Valgrind和调试器之类的工具实际上并不那么困难,只是乏味。
答案 1 :(得分:0)
我发现了问题。这是因为调用fib()时未重置链接列表的长度。谢谢大家的帮助。