我遇到了 AddressSanitizer:堆缓冲区溢出错误,用于最长回文子串。

huangapple go评论66阅读模式
英文:

I am getting AddressSanitizer: heap-buffer-overflow error for longest palindrome substring

问题

以下是您要翻译的内容:

我尝试解决的问题是LeetCode上的最长回文子串问题。

当我在DEVC++上运行我的代码时,它完全正常,但当我尝试在LeetCode上运行时,它会出现"AddressSanitizer: heap-buffer-overflow on address"运行时错误。我曾经请Chat-GPT帮我纠正我的代码,但似乎他没有做任何更改,但他的代码仍然在LeetCode上运行正常(我也会添加它)。我做错了什么?

char* longestPalindrome(char* s) {
    int i = 0;
    int j = 0;
    
    int high_i = 0;
    int high_j = 0;
    
    int maxlen = 0;
    int leng = strlen(s);
	
    for(i = 0; i < strlen(s); i++)
    {
        for(j = 0; s[i - j] == s[i + j] && (i - j) >= 0 && i + j < leng ; j++) // 用于奇数长度的回文串
        {// 检查索引是否越界
            if(((j >= high_j))) 
            {	
                high_j = j;
                high_i = i;
                
                maxlen = (2 * high_j) + 1;
            }
        }
    }
    for(i = 0; i < leng; i++)
    {
    	for(j = 0; s[i - j] == s[i + j + 1] && (i - j) >= 0 && i + j < leng - 1; j++) // 用于偶数长度的子串
		{																			// 确保索引不越界
			if((j + 1) * 2 > maxlen) // 比较回文串长度
			{
				high_j = j;
                high_i = i;
                maxlen = (1 + j) * 2;	
			}
		} 
	}
    char* result = malloc(sizeof(char) * (maxlen + 1)); // 为返回字符串分配内存
    strncpy(result, s + high_i - high_j, maxlen); // 从(i - j)复制到maxlen到结果字符串
    result[maxlen] = '
char* longestPalindrome(char* s) {
int i = 0;
int j = 0;
int high_i = 0;
int high_j = 0;
int maxlen = 0;
int leng = strlen(s);
for(i = 0; i < strlen(s); i++)
{
for(j = 0; s[i - j] == s[i + j] && (i - j) >= 0 && i + j < leng ; j++) // 用于奇数长度的回文串
{// 检查索引是否越界
if(((j >= high_j))) 
{	
high_j = j;
high_i = i;
maxlen = (2 * high_j) + 1;
}
}
}
for(i = 0; i < leng; i++)
{
for(j = 0; s[i - j] == s[i + j + 1] && (i - j) >= 0 && i + j < leng - 1; j++) // 用于偶数长度的子串
{																			// 确保索引不越界
if((j + 1) * 2 > maxlen) // 比较回文串长度
{
high_j = j;
high_i = i;
maxlen = (1 + j) * 2;	
}
} 
}
char* result = malloc(sizeof(char) * (maxlen + 1)); // 为返回字符串分配内存
strncpy(result, s + high_i - high_j, maxlen); // 从(i - j)复制到maxlen到结果字符串
result[maxlen] = '\0'; // 在字符串末尾添加null终止符
return result;
}
'; // 在字符串末尾添加null终止符 return result; }

这是Chat-GPT的代码:

char* longestPalindrome(char* s) {
    int i = 0;
    int j = 0;
    int high_i = 0;
    int high_j = 0;
    int maxlen = 0;
    int leng = strlen(s);

    for (i = 0; i < leng; i++) {
        for (j = 0; (i - j) >= 0 && (i + j) < leng && s[i - j] == s[i + j]; j++) {
            if (j >= high_j) {
                high_j = j;
                high_i = i;
                maxlen = (2 * high_j) + 1;
            }
        }
    }

    for (i = 0; i < leng; i++) {
        for (j = 0; (i - j) >= 0 && (i + j + 1) < leng && s[i - j] == s[i + j + 1]; j++) {
            if ((j + 1) * 2 > maxlen) {
                high_j = j;
                high_i = i;
                maxlen = (j + 1) * 2;
            }
        }
    }

    char* result = (char*)malloc(sizeof(char) * (maxlen + 1));
    strncpy(result, s + high_i - high_j, maxlen);
    result[maxlen] = '
char* longestPalindrome(char* s) {
int i = 0;
int j = 0;
int high_i = 0;
int high_j = 0;
int maxlen = 0;
int leng = strlen(s);
for (i = 0; i < leng; i++) {
for (j = 0; (i - j) >= 0 && (i + j) < leng && s[i - j] == s[i + j]; j++) {
if (j >= high_j) {
high_j = j;
high_i = i;
maxlen = (2 * high_j) + 1;
}
}
}
for (i = 0; i < leng; i++) {
for (j = 0; (i - j) >= 0 && (i + j + 1) < leng && s[i - j] == s[i + j + 1]; j++) {
if ((j + 1) * 2 > maxlen) {
high_j = j;
high_i = i;
maxlen = (j + 1) * 2;
}
}
}
char* result = (char*)malloc(sizeof(char) * (maxlen + 1));
strncpy(result, s + high_i - high_j, maxlen);
result[maxlen] = '\0';
return result;
}
'; return result; }

完整的错误代码如下:

=================================================================
==22==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200000000f at pc 0x55de54d7590e bp 0x7ffea23781a0 sp 0x7ffea2378190
READ of size 1 at 0x60200000000f thread T0
    #2 0x7f8076b44082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082)
0x60200000000f is located 1 bytes to the left of 6-byte region [0x602000000010,0x602000000016)
allocated by thread T0 here:
    #0 0x7f807778c808 in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cc:144
    #3 0x7f8076b44082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082)
Shadow bytes around the buggy address:
  0x0c047fff7fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c047fff8000: fa[fa]06 fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8010: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  

<details>
<summary>英文:</summary>

The problem I tried to solve is the longest palindrome substring problem on LeetCode.

When I run my code on DEVC++ it works perfectly fine, but when I try to run on leetcode it gives this &quot;AddressSanitizer: heap-buffer-overflow on address&quot; runtime error. I asked Chat-GPT to correct my code but it seems like he didn&#39;t change anything but still his code works on leetcode (I will add it too). What I am doing wrong?

char* longestPalindrome(char* s) {
int i = 0;
int j = 0;

int high_i = 0;
int high_j = 0;

int maxlen = 0;
int leng = strlen(s);

for(i = 0; i &lt; strlen(s); i++)
{
    for(j = 0; s[i - j] == s[i + j] &amp;&amp; (i - j) &gt;= 0 &amp;&amp; i + j &lt; leng ; j++) // for odd number length palindromes
    {// checking index is not out of range
        if(((j &gt;= high_j))) 
        {	
            high_j = j;
            high_i = i;
            
            maxlen = (2 * high_j) + 1;
        }
    }
}
for(i = 0; i &lt; leng; i++)
{
	for(j = 0; s[i - j] == s[i + j + 1] &amp;&amp; (i - j) &gt;= 0 &amp;&amp; i + j &lt; leng - 1; j++) // for even number length substrings
	{																			// making sure index is not out of range
		if((j + 1) * 2 &gt; maxlen) // compare palindrome length
		{
			high_j = j;
            high_i = i;
            maxlen = (1 + j) * 2;	
		}
	} 
}
char* result = malloc(sizeof(char) * (maxlen + 1)); // allocate memory for return string
strncpy(result, s + high_i - high_j, maxlen); // start copying (i - j) to maxlen to result string
result[maxlen] = &#39;
int high_i = 0;
int high_j = 0;
int maxlen = 0;
int leng = strlen(s);
for(i = 0; i &lt; strlen(s); i++)
{
for(j = 0; s[i - j] == s[i + j] &amp;&amp; (i - j) &gt;= 0 &amp;&amp; i + j &lt; leng ; j++) // for odd number length palindromes
{// checking index is not out of range
if(((j &gt;= high_j))) 
{	
high_j = j;
high_i = i;
maxlen = (2 * high_j) + 1;
}
}
}
for(i = 0; i &lt; leng; i++)
{
for(j = 0; s[i - j] == s[i + j + 1] &amp;&amp; (i - j) &gt;= 0 &amp;&amp; i + j &lt; leng - 1; j++) // for even number length substrings
{																			// making sure index is not out of range
if((j + 1) * 2 &gt; maxlen) // compare palindrome length
{
high_j = j;
high_i = i;
maxlen = (1 + j) * 2;	
}
} 
}
char* result = malloc(sizeof(char) * (maxlen + 1)); // allocate memory for return string
strncpy(result, s + high_i - high_j, maxlen); // start copying (i - j) to maxlen to result string
result[maxlen] = &#39;\0&#39;; // end null end of string
return result;
&#39;; // end null end of string return result;

}


And this one is Chat-GPT&#39;s

char* longestPalindrome(char* s) {
int i = 0;
int j = 0;
int high_i = 0;
int high_j = 0;
int maxlen = 0;
int leng = strlen(s);

for (i = 0; i &lt; leng; i++) {
    for (j = 0; (i - j) &gt;= 0 &amp;&amp; (i + j) &lt; leng &amp;&amp; s[i - j] == s[i + j]; j++) {
        if (j &gt;= high_j) {
            high_j = j;
            high_i = i;
            maxlen = (2 * high_j) + 1;
        }
    }
}

for (i = 0; i &lt; leng; i++) {
    for (j = 0; (i - j) &gt;= 0 &amp;&amp; (i + j + 1) &lt; leng &amp;&amp; s[i - j] == s[i + j + 1]; j++) {
        if ((j + 1) * 2 &gt; maxlen) {
            high_j = j;
            high_i = i;
            maxlen = (j + 1) * 2;
        }
    }
}

char* result = (char*)malloc(sizeof(char) * (maxlen + 1));
strncpy(result, s + high_i - high_j, maxlen);
result[maxlen] = &#39;
for (i = 0; i &lt; leng; i++) {
for (j = 0; (i - j) &gt;= 0 &amp;&amp; (i + j) &lt; leng &amp;&amp; s[i - j] == s[i + j]; j++) {
if (j &gt;= high_j) {
high_j = j;
high_i = i;
maxlen = (2 * high_j) + 1;
}
}
}
for (i = 0; i &lt; leng; i++) {
for (j = 0; (i - j) &gt;= 0 &amp;&amp; (i + j + 1) &lt; leng &amp;&amp; s[i - j] == s[i + j + 1]; j++) {
if ((j + 1) * 2 &gt; maxlen) {
high_j = j;
high_i = i;
maxlen = (j + 1) * 2;
}
}
}
char* result = (char*)malloc(sizeof(char) * (maxlen + 1));
strncpy(result, s + high_i - high_j, maxlen);
result[maxlen] = &#39;\0&#39;;
return result;
&#39;; return result;

}


Full error code is

=================================================================
==22==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200000000f at pc 0x55de54d7590e bp 0x7ffea23781a0 sp 0x7ffea2378190
READ of size 1 at 0x60200000000f thread T0
#2 0x7f8076b44082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082)
0x60200000000f is located 1 bytes to the left of 6-byte region [0x602000000010,0x602000000016)
allocated by thread T0 here:
#0 0x7f807778c808 in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cc:144
#3 0x7f8076b44082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082)
Shadow bytes around the buggy address:
0x0c047fff7fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c047fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c047fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c047fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c047fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c047fff8000: fa[fa]06 fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8010: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8050: 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: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==22==ABORTING


</details>


# 答案1
**得分**: 0

似乎你误解了短路运算的工作原理。当 C 评估表达式时,首先看 `s[i - j] == s[i + j]`,如果这个表达式评估为 `false`,那么它就会停止评估并跳过到条件的另一部分。为了正确使用短路运算,你应该将边界情况检查放在最左边,这样首先进行检查,因此在查看表达式的其余部分之前就会终止评估。

因此,你希望将 `(i - j) &gt;= 0` 放在表达式的前面。应该是这样的:

(i - j) >= 0 && s[i - j] == s[i + j]


这样,如果 `(i - j) &gt;= 0` 评估为 `false`,则条件部分会被跳过,以避免发生无效的内存访问。

这是维基百科上关于短路运算的一篇好文章:[短路求值](https://en.wikipedia.org/wiki/Short-circuit_evaluation)

此外,这是 C 的运算符优先级的补充信息:[C 运算符优先级](https://en.cppreference.com/w/c/language/operator_precedence)(这里重要的不是优先级,尽管这很重要,而是关联性,这会告诉你表达式的评估方向)。

<details>
<summary>英文:</summary>

It seems that you misunderstand how short-circuiting works. When C evaluates the expression 

s[i - j] == s[i + j] && (i - j) >= 0

It first looks at `s[i - j] == s[i + j]` and if this evaluates to `false` then it stops evaluating and skips to the else portion of the condition. To correctly use short-circuiting you want to put your edge case checking at the far left, so that it is checked first and so the evaluation is aborted prior to looking at the rest of the expression.

For this reason you want to put `(i - j) &gt;= 0` in front of the rest of the expression. So it should look like this:

(i - j) >= 0 && s[i - j] == s[i + j]

This way if `(i - j) &gt;= 0` evaluates to `false` then the conditional part of the expression is skipped so that the invalid memory access doesn&#39;t happen.

Here&#39;s a good article on short circuiting from wikipedia https://en.wikipedia.org/wiki/Short-circuit_evaluation

and as a supplement, here is the operator precedence for C https://en.cppreference.com/w/c/language/operator_precedence (the important thing to look at here isn&#39;t the precedence, though that is really important, it&#39;s the association, that will tell you the direction that expressions are evaluated)

</details>



huangapple
  • 本文由 发表于 2023年6月12日 06:59:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/76452829.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定