堆中断(未初始化段的末尾)附近存储了什么?
What is stored near the heap-break (end of uninitialized segment)?
在这个简单的代码中:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(){
void * first = sbrk(4096);
void *p = sbrk(0);
//sigterm, however were it (p-4) -> it could be derefenced
*((int*)(p-3)) = 1;
printf("%d\n",*(int*)(p-3));
}
如果我试图在堆末尾附近取消引用地址,我会遇到段错误。但是 B-16(其中 B 代表堆中断)是可取消引用的,而 B-12 不是(段错误)。那么堆的中断附近存储了哪些信息?
你不是在做 p-12 和 p-16,你在做 p-3 和 p-4。
你正在做 (int*)(p-3)
即你正在减去 3 然后 然后 转换为 int,而不是相反 ((int*)p)-3
。因此,编译器减去声明指向的任何类型 p
的 3 个,而不是 3 个整数。
该类型是 void
,因为 p
是 void*
。所以编译器减去 3 个字节。然后你读取 4 个字节,因为 int
在你的编译器上是 4 个字节。
注意: 从 void*
中减去是一个特定于 GCC 的扩展 - 一个不属于普通 C 的额外功能。一些编译器会给你一个错误,说你不能添加或减去 void*
指针。在那些编译器上,要减去 3 个字节,您必须强制转换为 char*
然后减去 3.
在这个简单的代码中:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(){
void * first = sbrk(4096);
void *p = sbrk(0);
//sigterm, however were it (p-4) -> it could be derefenced
*((int*)(p-3)) = 1;
printf("%d\n",*(int*)(p-3));
}
如果我试图在堆末尾附近取消引用地址,我会遇到段错误。但是 B-16(其中 B 代表堆中断)是可取消引用的,而 B-12 不是(段错误)。那么堆的中断附近存储了哪些信息?
你不是在做 p-12 和 p-16,你在做 p-3 和 p-4。
你正在做 (int*)(p-3)
即你正在减去 3 然后 然后 转换为 int,而不是相反 ((int*)p)-3
。因此,编译器减去声明指向的任何类型 p
的 3 个,而不是 3 个整数。
该类型是 void
,因为 p
是 void*
。所以编译器减去 3 个字节。然后你读取 4 个字节,因为 int
在你的编译器上是 4 个字节。
注意: 从 void*
中减去是一个特定于 GCC 的扩展 - 一个不属于普通 C 的额外功能。一些编译器会给你一个错误,说你不能添加或减去 void*
指针。在那些编译器上,要减去 3 个字节,您必须强制转换为 char*
然后减去 3.