You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

realloc因堆大小受限触发SIGABRT的复现及堆限制方法咨询

问题分析与示例代码

1. 报错原因纠正

你触发的错误是glibc malloc的安全校验失败,抛出realloc(): invalid pointer错误后主动触发SIGABRT,并非堆空间不足导致:

  • 堆空间不足时realloc只会返回NULL,不会直接终止程序
  • 该校验失败的常见原因:传入realloc的指针不是动态分配返回的合法指针、指针已被提前释放、堆上的元数据被越界写等操作篡改。

你定位到的glibc 2.27 malloc.c 3174行的代码逻辑就是校验传入的oldp指针是否符合堆chunk的对齐规则、地址是否合法,校验不通过就直接抛出错误终止进程。

2. 限制堆大小的示例代码

可以通过setrlimit的RLIMIT_DATA参数限制进程的堆区域最大大小,注意:受操作系统页对齐规则、glibc malloc本身的元数据开销限制,设置10字节限制后实际可分配的用户内存会远小于常规4KB页的大小,示例代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <sys/resource.h>
#include <errno.h>

int main() {
    // 设置堆最大限制为10字节
    struct rlimit rl = {
        .rlim_cur = 10,
        .rlim_max = 10
    };
    if (setrlimit(RLIMIT_DATA, &rl) != 0) {
        perror("setrlimit failed");
        return 1;
    }

    // 尝试分配内存复现问题
    void* ptr = calloc(1, 2);
    if (!ptr) {
        perror("calloc failed");
        return 1;
    }
    printf("calloc success, ptr = %p\n", ptr);

    // 尝试扩容触发错误
    void* new_ptr = realloc(ptr, 8);
    if (!new_ptr) {
        perror("realloc failed");
        free(ptr);
        return 1;
    }
    printf("realloc success, new_ptr = %p\n", new_ptr);

    free(new_ptr);
    return 0;
}

编译运行命令:gcc test.c -o test && ./test
如果想要更精准的控制堆分配行为,还可以配合mallopt调整glibc malloc的参数,关闭mmap分配大内存的 fallback 逻辑,避免超出堆限制时malloc改用mmap分配内存。

内容的提问来源于stack exchange,提问作者Learner09

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 12:30:00