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

malloc/free触发Signal 6错误:栈实现代码的内存越界问题排查

你的栈实现触发Abort的原因与修复方案

嘿,我来帮你搞定这个问题——你的栈代码里的pop函数藏着个内存越界的坑,直接破坏了堆内存结构,才导致glibc在free的时候炸出invalid pointer错误,最终触发Signal 6(abort)。

问题出在哪?

先看pop里的缩容逻辑:

int *arr2 = (int*)malloc(sizeof(int) * size / 2);
for ( i = 0; i < size; i++) 
    arr2[i] = arr[i];

你申请了只有原数组一半大小的新内存(size/2),但循环却硬要把原数组的size个元素全复制过去!这就导致新数组的后半段是不属于它的内存,写入这些位置会直接破坏malloc用来管理堆的元数据。这种堆损坏不会立刻报错,但等你调用free(arr)的时候,glibc的堆检测机制发现内存块的管理信息被篡改,就直接触发abort终止程序了。

另外还有个小隐患:你没判断栈是否为空,如果top已经是0还调用pop,--top会变成负数,访问arr[负数索引]又是一次越界。

修复后的完整代码

#include <stdlib.h>

int *arr; 
int size = 2; 
int top = 0; 

int pop() {
    // 先检查栈是否为空,避免空栈pop导致越界
    if (top == 0) {
        // 这里可以根据需求返回错误码,或者直接终止,示例用abort
        abort();
    }
    
    // 先取出要返回的值,再处理缩容
    int popped_val = arr[--top];
    
    // 缩容条件:栈元素不到当前容量的1/4,且容量大于2(避免缩到0)
    if (top <= size / 4 && size > 2) {
        int new_size = size / 2;
        int *arr2 = (int*)malloc(sizeof(int) * new_size);
        
        // 只复制栈里的有效元素(共top个),不是原数组的全部size个
        for (int i = 0; i < top; i++) {
            arr2[i] = arr[i];
        }
        
        free(arr);
        arr = arr2;
        size = new_size;
    }
    
    return popped_val;
}

void push(int a) {
    if (top >= size) {
        int new_size = size * 2;
        int *arr2 = (int*)malloc(sizeof(int) * new_size);
        
        // push扩容时复制原数组全部size个元素是对的,因为原数组全是有效元素
        for (int i = 0; i < size; i++) {
            arr2[i] = arr[i];
        }
        
        free(arr);
        arr = arr2;
        size = new_size;
    }
    arr[top++] = a;
}

关键修复点说明

  1. 修正缩容时的复制范围:缩容只需要复制当前栈里的top个有效元素(而不是原数组的size个),既避免了越界写,也没必要复制那些已经弹出的无效数据。
  2. 添加空栈判断:防止pop空栈时出现负数索引的越界访问,避免后续更隐蔽的内存问题。
  3. 限制缩容下限:加了size > 2的判断,避免数组被缩到0,导致后续push时无法正常扩容。

为什么之前的报错指向free?

堆内存的管理信息(比如内存块的大小、前后块指针)是存在内存块周围的,你越界写入新数组时,刚好覆盖了这些信息。当你调用free(arr)时,glibc会检查这些管理信息是否合法,发现被篡改后就直接触发abort,所以报错看起来是free的问题,但根源是之前的越界写。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:25:06