访问特定指针时出现分段错误

Segmentation fault when accessing specific pointer

我正尝试在 C 中为一个项目编写我自己的 malloc 和 free。在大多数情况下,一切都很好,但我无法解决它给我的一个奇怪的分段错误。我以简化形式重现了给出错误的代码:

#include <stdio.h>

#define MEMORY_SIZE 4096
static char memory[MEMORY_SIZE];

typedef struct metaData{
    unsigned short isFree; //1 if free, 0 if allocated
    unsigned short size;
} metaData;

int main(){
    metaData *head = (metaData *) memory;
    printf("%d\n", (head+2031)->size);
    printf("%d\n", (head+2032)->size);
    puts("Segmentation up here???");

    return 0;
}

memory 是一个大小为 4096 的静态字符数组。第一个 printf 打印出 0。但下一个 printf 是一个段错误。我能够在 head+2032 之前的每个指针处操作 metaData 结构。有人知道为什么吗?

C 中的指针运算以 pointed-to 类型 的 大小的基本单位执行。您的 head 是指向 metaData 结构的指针,其大小为 2 × sizeof(unsigned short)。假设(很可能,但不确定)unsigned short 在您的平台上的大小为 2 个字节,那么“基本单位”将为 4 个字节。

因此,当进行 head + 2031 计算时,4 × 2031 的值(即 8124)将被添加到 head 中的地址以给出该表达式的结果.因此,使用以下 ->size 运算符,您试图从 memory 数组的开头位置引用 8,126 字节 1 的内存——但是数组被声明为只有 4096 字节sizeof(char) 根据定义是 1 个字节)。

访问超出数组声明大小的内存是未定义行为 (UB);一旦你调用了这样的 UB(就像你在 both printf 调用中所做的那样),许多不同的事情就会发生,并且以不可预测的方式发生。 “分段错误”(尝试读取或写入您的程序无权访问的内存)是 UB 的一种可能表现形式。 (另一种可能的表现是没有报错,程序看起来正常运行,在很多人看来,这是最糟糕的一种!)


1 8,124 字节将是潜在 pointed-to meteData 结构开始的偏移量;因为 size 前面有另一个 unsigned short 成员,那么将添加另外两个字节。