本文主要是介绍本地能运行的C程序,为什么在LeetCode上会失败?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
在做LeetCode第22题时,https://leetcode-cn.com/problems/generate-parentheses/
我一开始写了下面这些代码
void generateOneByOne(char *sublist, char ***result, int left, int right, int index, int* returnSize)
{//终止条件,使用完所有的括号if (left == 0 && right == 0){int new_size = *returnSize + 1;//如果原来为空if ( *result == NULL ) {*result = (char **)malloc( sizeof(char*) * new_size);} else{//如果不为空,则要重新分配下内存*result = (char **)realloc(*result, new_size * sizeof(char *));}//增加新的数据(*result)[*returnSize] = (char *)malloc( sizeof(char) * strlen(sublist) );strcpy((*result)[*returnSize], sublist);*returnSize = new_size;}if ( left > 0){sublist[index] = '(';index++;generateOneByOne(sublist, result, left - 1, right, index, returnSize);//恢复现场index--;}if ( right > left){sublist[index] = ')';index++;generateOneByOne(sublist, result, left, right - 1, index, returnSize);index--;}}
//result, 一开始**result
char ** generateParenthesis(int n, int* returnSize){int str_len = n * 2 + 1;char *substring = (char *)malloc(sizeof(char) * str_len);substring[str_len] = '\0';char **result = NULL;generateOneByOne(substring, &result, n, n,0, returnSize);return result;}
在本地运行的时候,是没有任何问题,而在LeetCode上运行时, 就报错了,
=================================================================
==29==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000014 at pc 0x000000401d79 bp 0x7ffe252ab3d0 sp 0x7ffe252ab3c8
WRITE of size 1 at 0x602000000014 thread T0#2 0x7f36d55b22e0 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x202e0)
0x602000000014 is located 0 bytes to the right of 4-byte region [0x602000000010,0x602000000014)
allocated by thread T0 here:#0 0x7f36d6e612b0 in malloc (/usr/local/lib64/libasan.so.5+0xe82b0)#3 0x7f36d55b22e0 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x202e0)
Shadow bytes around the buggy address:0x0c047fff7fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000x0c047fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000x0c047fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000x0c047fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000x0c047fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c047fff8000: fa fa[04]fa fa fa fa fa fa fa fa fa fa fa fa fa0x0c047fff8010: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa0x0c047fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa0x0c047fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa0x0c047fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa0x0c047fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):Addressable: 00Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: faFreed heap region: fdStack left redzone: f1Stack mid redzone: f2Stack right redzone: f3Stack after return: f5Stack use after scope: f8Global redzone: f9Global init order: f6Poisoned by user: f7Container overflow: fcArray cookie: acIntra object redzone: bbASan internal: feLeft alloca redzone: caRight alloca redzone: cb
==29==ABORTING
错误太长,而且我也看不懂。于是我按照我的经验,检索了" AddressSanitizer: heap-buffer-overflow "相关内容,一个可靠回答在https://stackoverflow.com/questions/51579267/addresssanitizer-heap-buffer-overflow-on-address。
简单都说,就是通常的C编译器是不会检查边界问题的,也就是如果我定义了int a[10]
,我访问a[100]
也不会提示错误。但是,如果你在编译的时候加上-fsanitize=address
参数,程序运行的时候就会做边界检查,在越界的时候报错。
因此我的源代码中存在了我没有发现的越界行为,你能看出是哪里吗?
第一处是substring[str_len] = '\0'
, 大小为N的数组,最后一位是N-1。
第二处错误在(*result)[*returnSize] = (char *)malloc( sizeof(char) * strlen(sublist) );
中,新申请的内存大小应该是sizeof(char) * (strlen(sublist) + 1)
, 需要放在最后的'\0';
此外,对于这种“明明我可以”的报错,官方建议你绕行C/C++,换个编程语言
C/C++
The most frequent culprit causing undefined behavior is out-of-bounds array access. These bugs could be hard to debug, so good luck. Or just give up on C/C++ entirely and code in a more predictable language, like Java. :)
这篇关于本地能运行的C程序,为什么在LeetCode上会失败?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!