C++ 分段错误:11 错误,同时编码将两个数字相加的链接列表

C++ Segmentation fault: 11 Error, while coding linkedlist that adds two numbers

本文关键字:错误 数字 两个 列表 链接 分段 编码 C++      更新时间:2023-10-16

我有如下代码:

#include <iostream>
struct ListNode
{
int val;
ListNode *next;
ListNode() : val(0), next(nullptr){} 
ListNode(int x) : val(x), next(nullptr){} 
ListNode(int x, ListNode *next) : val(x), next(next){}
};
void print(ListNode *head) {
ListNode *l = head;
while (l)
{
std::cout << "val is " << l->val << std::endl;
l = l->next;
}
}
ListNode *addTwoNumbers(ListNode *l1, ListNode *l2)
{
int sum = 0, quo = 0, rem = 0;
ListNode *head = (ListNode *)malloc(sizeof(ListNode));
ListNode *curr, *prev = nullptr;
while (l1 || l2)
{
// Calculate value
sum = (l1->val + l2->val + quo);
quo = sum / 10;
rem = sum - quo * 10;
// Add node
if(prev == nullptr) {
curr = head;
} else {
curr = (ListNode *)malloc(sizeof(ListNode));
prev->next = curr;
}
curr->val = rem;
prev = curr;
l1 = l1->next;
l2 = l2->next;
}
return head;
}

int main() {
ListNode *node1_1 = (ListNode *)malloc(sizeof(ListNode));
ListNode *node1_2 = (ListNode *)malloc(sizeof(ListNode));
ListNode *node1_3 = (ListNode *)malloc(sizeof(ListNode));
node1_1->val = 2;
node1_2->val = 4;
node1_3->val = 3;
node1_1->next = node1_2;
node1_2->next = node1_3;
ListNode *node2_1 = (ListNode *)malloc(sizeof(ListNode));
ListNode *node2_2 = (ListNode *)malloc(sizeof(ListNode));
ListNode *node2_3 = (ListNode *)malloc(sizeof(ListNode));
node2_1->val = 5;
node2_2->val = 6;
node2_3->val = 4;
node2_1->next = node2_2;
node2_2->next = node2_3;
free(node1_1);
free(node1_2);
free(node1_3);
free(node2_1);
free(node2_2);
free(node2_3);
print(addTwoNumbers(node1_1, node2_1));
}

问题是,当我尝试在 vscode 上运行此代码时, 我不断收到错误:

/bin/sh: line 1: 96278 Segmentation fault: 11 "/Users/cpp/"leet_add_two_nums

我怀疑这个问题与malloc有关,但找不到线索。

我试图在malloc之后释放,但这不是问题所在。

我对C++很陌生,有人可以帮忙吗?

另外,如果有人告诉我如何改进我的代码,我将不胜感激!

提前非常感谢!

while (l1 || l2)

这意味着"虽然l1nullptrl2nullptr,但请继续循环!

你想要一个 AND 那里:

while(l1 && l2)

此外,您可以在调用addTwoNumbers之前释放列表中的所有节点!将您的addTwoNumbers呼叫移至所有free之前。

在这里看到它运行:https://ideone.com/f4kBIh

通过将malloc替换为">new"可以轻松解决此问题

使用">"具有以下好处:

  • 使程序能够灵活应对 malloc 的常见问题。
  • 不再需要显式调用"free"。

以下是将malloc替换为new的工作代码:

#include <iostream>
struct ListNode {
int val;
ListNode *next;
ListNode() : val(0), next(nullptr){} 
ListNode(int x) : val(x), next(nullptr){} 
ListNode(int x, ListNode *next) : val(x), next(next){}
};
void print(ListNode *head) {
ListNode *l = head;
while (l) {
std::cout << "val is " << l->val << std::endl;
l = l->next;
}
}
ListNode *addTwoNumbers(ListNode *l1, ListNode *l2) {
int sum = 0, quo = 0, rem = 0;
ListNode *head = new ListNode[(sizeof(ListNode))];
ListNode *curr, *prev = nullptr;
while (l1 || l2) {
// Calculate value
sum = (l1->val + l2->val + quo);
quo = sum / 10;
rem = sum - quo * 10;
// Add node
if(prev == nullptr) {
curr = head;
} else {
curr = new ListNode[(sizeof(ListNode))];
prev->next = curr;
}
curr->val = rem;
prev = curr;
l1 = l1->next;
l2 = l2->next;
}
return head;
}
int main() {
ListNode *node1_1 = new ListNode[(sizeof(ListNode))];
ListNode *node1_2 =  new ListNode[(sizeof(ListNode))];
ListNode *node1_3 =  new ListNode[(sizeof(ListNode))];
node1_1->val = 2;
node1_2->val = 4;
node1_3->val = 3;
node1_1->next = node1_2;
node1_2->next = node1_3;
ListNode *node2_1 = new ListNode[(sizeof(ListNode))];
ListNode *node2_2 = new ListNode[(sizeof(ListNode))];
ListNode *node2_3 = new ListNode[(sizeof(ListNode))];
node2_1->val = 5;
node2_2->val = 6;
node2_3->val = 4;
node2_1->next = node2_2;
node2_2->next = node2_3;
print(addTwoNumbers(node1_1, node2_1));
}

输出:

val is 7
val is 0
val is 8

好的,所以关于这段代码的一些评论

构造函数在类中很棒,但是如果您使用 C malloc,则不会执行构造函数。

对类/结构使用newdelete,例如 ListNode,这样接下来实际上将是空的,正如您在构造函数中指定的那样,否则它将未初始化

您的同时循环

while (l1 || l2) 

将继续,直到两者都为 null,但如果其中一个碰巧变为 null,您将取消重新引用它,因为另一个可能不为 null:

l1 = l1->next;
l2 = l2->next;

(顺便说一句,使用更好的变量名称,使用简短,神秘的变量名称没有优势(

在你的主函数中 - 你已经释放了node1_1和node1_2的内存,但仍然在你的函数调用print(addTwoNumbers(node1_1,node2_1))中使用它

int main() {
ListNode *node1_1 = (ListNode *)malloc(sizeof(ListNode));
ListNode *node1_2 = (ListNode *)malloc(sizeof(ListNode));
ListNode *node1_3 = (ListNode *)malloc(sizeof(ListNode));
node1_1->val = 2;
node1_2->val = 4;
node1_3->val = 3;
node1_1->next = node1_2;
node1_2->next = node1_3;
ListNode *node2_1 = (ListNode *)malloc(sizeof(ListNode));
ListNode *node2_2 = (ListNode *)malloc(sizeof(ListNode));
ListNode *node2_3 = (ListNode *)malloc(sizeof(ListNode));
node2_1->val = 5;
node2_2->val = 6;
node2_3->val = 4;
node2_1->next = node2_2;
node2_2->next = node2_3;
free(node1_1);
free(node1_2);
free(node1_3);
free(node2_1);
free(node2_2);
free(node2_3);
print(addTwoNumbers(node1_1, node2_1));  <<== node1_1,node2_1, already freed
}

而是做这样的事情

#include <iostream>
int main() {
auto node1_1 = new ListNode;
auto node1_2 = new ListNode;
auto node1_3 = new ListNode;
node1_1->val = 2;
node1_2->val = 4;
node1_3->val = 3;
node1_1->next = node1_2;
node1_2->next = node1_3;
ListNode *node2_1 = new ListNode;
ListNode *node2_2 = new ListNode;
ListNode *node2_3 = new ListNode;
node2_1->val = 5;
node2_2->val = 6;
node2_3->val = 4;
node2_1->next = node2_2;
node2_2->next = node2_3;
std::cout << addTwoNumbers(node1_1, node2_1); 
delete node1_1;
delete node1_2;
delete node1_3;
delete node2_1;
delete node2_2;
delete node2_3;
}