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

为何写入some_data[some_data_size]会导致free()调用时程序崩溃?

问题分析:内存越界写入导致free()崩溃的原因

这段C代码中,执行some_data[some_data_size] = '\0';后调用free()会触发崩溃,移除该行则崩溃消失。以下是针对该问题的具体分析:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    FILE* fd = fopen("junk.txt", "r");
    int buffer_size = 42; //random number just for this example
    if (fd != NULL)
    {
        char* data = calloc(buffer_size, sizeof(uint8_t));
        if (data != NULL)
        {
            uint32_t read_size = fread(data, 1, buffer_size, fd);
            if (read_size == buffer_size)
            {
                char* some_data = strstr(data, "DATA:");
                if (some_data != NULL)
                {
                    uint32_t some_data_size = some_data - data;
                    char* stuff = calloc(some_data_size + 1, sizeof(uint8_t));
                    if (stuff != NULL)
                    {
                        some_data[some_data_size] = '\0'; // removing this line prevents a crash
                        //... doing stuff with the data
                        memcpy(stuff, some_data + 6, some_data_size);
                        free(stuff);
                    }
                }
            }
            fclose(fd);
            free(data);
        }
    }
    return 0;
}

1. 核心问题:非法的内存越界写入

  • some_data_size的计算逻辑是some_data - data,得到的是"DATA:"在data数组中的起始偏移量(从data开头到some_data的字节数)。
  • some_data[some_data_size]等价于*(some_data + some_data_size),也就是*(data + (some_data - data) + some_data_size),最终指向data + 2*some_data_size的位置。
  • 由于data的总大小只有buffer_size(示例中是42),只要2*some_data_size > buffer_size,这个写入操作就会直接越界,访问data分配内存之外的区域。即使2*some_data_size刚好小于等于buffer_size,这个位置也不属于"DATA:"对应的有效内容范围,同样可能覆盖后续的有效数据或堆元数据。

2. 越界写入为何会导致free()崩溃?

  • 堆内存分配函数(malloc/calloc)会在分配的内存块前后维护元数据,比如块的大小、下一个空闲块的指针等,用于管理堆空间的分配与释放。
  • 越界写入会直接破坏这些元数据,当free()尝试读取元数据来回收内存时,会遇到非法内存访问、堆结构损坏等问题,最终触发程序崩溃。
  • 移除some_data[some_data_size] = '\0';后,没有破坏堆的元数据,free()就能正常执行堆内存的回收操作。

3. 正确的处理方式

如果需要给some_data指向的内容添加终止符,必须确保写入位置在data的合法内存范围内:

  • 先计算some_data到data末尾的剩余空间:size_t remaining = buffer_size - (some_data - data);
  • 确保写入终止符的位置(比如some_data + offset)小于data + buffer_size,例如如果要在"DATA:"之后处理字符串,需要保证终止符写入的位置不超过data的边界。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 18:37:29