返回动态分配的块时出现堆缓冲区溢出运行时错误

Heap-buffer-overflow runtime error when returning a dynamically allocated block

提问人: 提问时间:1/11/2023 最后编辑:Clifford 更新时间:1/12/2023 访问量:147

问:

我最近开始用 C 语言编程,遇到了返回数组的问题。当我尝试返回数组时,出现堆缓冲区溢出运行时错误。

这是我的代码

int* getConcatenation(int* nums, int numsSize, int* returnSize){
    int *ans;
    ans=(int*)malloc(numsSize * sizeof(int));
    for (int i=0;i<numsSize;i++){
        ans[i]=nums[i];
        ans[i+numsSize]=nums[i];
    }
    free(ans);
    return ans;
}

错误

AddressSanitizer: heap-buffer-overflow on address 0x60200000003c at pc 0x55780cb25d30 bp 0x7ffd83067af0 sp 0x7ffd83067ae0
WRITE of size 4 at 0x60200000003c thread T0
    #2 0x7fabeed390b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
0x60200000003c is located 0 bytes to the right of 12-byte region [0x602000000030,0x60200000003c)
allocated by thread T0 here:
    #0 0x7fabef97ebc8 in malloc (/lib/x86_64-linux-gnu/libasan.so.5+0x10dbc8)
    #3 0x7fabeed390b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
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 00 04 fa fa 00[04]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
==44==ABORTING

更改代码:

这是我现在的代码,但它仍然不起作用

int* getConcatenation(int* nums,
                      int numsSize, 
                      int* returnSize)
{
    int *ans;
    ans=malloc(2*numsSize * sizeof(int));
    for (int i=0;i<numsSize;i++)
    {
        ans[i]=nums[i];
        ans[i+numsSize]=nums[i];
    }

    return ans;
}
数组 c 返回 运行时错误 malloc

评论

3赞 David Ranieri 1/11/2023
ans[i+numsSize]=nums[i];在数组的边界之外写入
3赞 Oka 1/11/2023
你认为有什么作用?free(ans); return ans;
1赞 Eugene Sh. 1/11/2023
@Clifford 通过引入阴谋:)令人鼓舞
2赞 Clifford 1/11/2023
@Fe2O3 : 是的,这就是我的观点。不确定你在说什么?
2赞 Clifford 1/11/2023
@Fe2O3 : 对不起,这是漫长的一天。理解。

答:

1赞 Clifford 1/11/2023 #1

访问:

ans[i+numsSize]=nums[i];

远远超出了已分配空间的范围。你需要;

ans = malloc(2 * numsSize * sizeof(int))

您可以返回 .您不能做的是访问它指向的内存,因为您使用 .这使得它可以重复使用。ansfree()

即使删除了,在大多数情况下,无论如何,这都是一种不明智的模式。通过在函数中分配内存,您将依赖于调用方知道内存必须为“d”。通常,最好将分配与发布放在相同的范围内(就像您所做的那样,但在错误的范围内)。更惯用的模式是让调用方提供内存并将指针传递到函数中。这样,内存甚至不需要动态分配,它由调用者控制。free()free

malloc()返回 A 它不需要被强制转换,这样做是不好的做法。void*

评论

0赞 Dúthomhas 1/11/2023
不同意“这是一种不明智的模式”。各种库中的许多现有函数将为您提供一个指向可以使用的数据的指针,并期望您直接使用或通过调用释放函数来释放它。 是标准 libc 中内容的一个例子。 是你的例子。free()strdup()malloc()
0赞 1/11/2023
我更改了内存分配器并删除了 free(),但我的代码仍未完成。它不会返回任何内容。
0赞 Clifford 1/12/2023
@Dúthomhas 它发生很多次并不意味着它是一个好主意,当然,它经常发生的事实,显然很多人会不同意(尽管他们也可能是那些代码泄漏、有缺陷的人)。也许是我在嵌入式系统领域 33 年的背景形成了我的观点。是的是一个例子,也是许多内存泄漏错误的原因。问题在于,它在命名中宣传其行为,并且标准库被精心记录并且其行为保持不变。strdup()malloc()
0赞 Clifford 1/12/2023
@ДенисМороз : 我无法评论看不见的代码。上述所有问题都解决了代码中的缺陷。如果您现在有不同的代码和不同的错误,那么这是针对不同的问题。显然,它返回了一些东西。只有函数不返回任何内容void
0赞 1/12/2023
我添加了新代码,但它仍然不起作用。