LeetCode第2题Add Two Numbers代码遇内存对齐运行时错误求助
LeetCode第2题「Add Two Numbers」C语言实现错误分析
问题背景
我正在用C语言解决LeetCode第2题「Add Two Numbers」,题目要求:
给定两个非空链表,分别表示两个逆序存储的非负整数,每个节点存一位数字,将两数相加后以逆序链表形式返回。
题目示例:
Input: l1 = [2,4,3], l2 = [5,6,4]
Output: [7,0,8]
Explanation: 342 + 465 = 807.
LeetCode提供的结构体定义:
struct ListNode { int val; struct ListNode *next; };
我的实现代码如下:
struct ListNode *addTwoNumbers(struct ListNode *l1, struct ListNode *l2) { int number1 = 0; int reverse1 = 0; int rotate = 1; int addnumbers; struct ListNode *final = (struct ListNode *)malloc(sizeof(struct ListNode)); struct ListNode *current = final; int split; while (l1 != NULL) { number1 = (l1->val * rotate) + number1; l1 = l1->next; rotate = rotate * 10; } int number2 = 0; reverse1 = 0; rotate = 1; while (l2 != NULL) { number2 = (l2->val * rotate) + number2; l2 = l2->next; rotate = rotate * 10; } addnumbers = number1 + number2; while (addnumbers != 0) { split = addnumbers % 10; addnumbers = addnumbers / 10; if (final != NULL) { final->val = split; printf("%d \n", final->val); } if (addnumbers == 0) { final->next = NULL; break; } else { final->next = malloc(sizeof(struct ListNode)); } final = final->next; } while (current != NULL) { printf(" The values are %d \n", current->val); current = current->next; } return 0; }
遇到的问题
代码执行时能打印出正确的数值,但会额外打印垃圾值,同时出现运行时错误:
Line 58: Char 9: runtime error: member access within misaligned address 0xbebebebebebebebe for type 'struct ListNode', which requires 8 byte alignment [solution.c] 0xbebebebebebebebe: note: pointer points here <memory cannot be printed>
我认为最后一个while循环应仅执行3次,却出现了第4次执行的情况,想请教该错误的原因。
错误原因分析
1. 核心逻辑缺陷:整数溢出风险
将链表转成整数相加的思路存在本质问题:当链表长度超过int的位数限制(比如10位以上),number1或number2会直接溢出,导致计算结果完全错误。LeetCode的测试用例必然包含大数场景,这个思路根本无法通过所有测试。
2. 触发运行时错误的直接原因
- 返回值错误:函数最后执行
return 0;,完全不符合题目要求。LeetCode要求返回结果链表的头节点(即代码中的current指针),返回空指针会导致评测系统尝试访问NULL->val,触发内存错误,也就是你看到的0xbebebebebebebebe(该地址是内存被标记为无效的典型标记值)。 - 边界情况未处理:当两个链表相加结果为0时(比如l1=[0], l2=[0]),
while(addnumbers != 0)循环不会执行,此时final节点的val和next均为未初始化的垃圾值,遍历打印时会访问非法内存,触发错误。
3. 遍历循环多执行的原因
在你的示例场景中,遍历循环本应执行3次,但出现第4次的情况,大概率是因为某个节点的next指针被赋了垃圾值。比如如果代码在某些分支下未正确设置final->next = NULL,就会导致遍历到非法内存地址,看起来像是多执行了一次循环。
修正后的实现思路
正确的做法是直接对链表节点逐位相加,处理进位,避免整数溢出:
struct ListNode *addTwoNumbers(struct ListNode *l1, struct ListNode *l2) { struct ListNode dummy; // 哑节点,简化头节点的创建和处理 struct ListNode *current = &dummy; int carry = 0; // 遍历两个链表,直到所有节点处理完且无进位 while (l1 != NULL || l2 != NULL || carry != 0) { int sum = carry; if (l1 != NULL) { sum += l1->val; l1 = l1->next; } if (l2 != NULL) { sum += l2->val; l2 = l2->next; } carry = sum / 10; // 计算进位 // 创建新节点存储当前位结果 current->next = malloc(sizeof(struct ListNode)); current->next->val = sum % 10; current->next->next = NULL; current = current->next; } return dummy.next; // 返回结果链表的头节点 }
这个实现能正确处理所有边界情况,包括大数相加,且符合题目要求返回正确的链表结构。
内容的提问来源于stack exchange,提问作者Gautam Anew
相关产品推荐
相关产品推荐

