das*_*man 7 c memory heap stack gcc
在像Linux这样的需求分页系统中,页面可能比我读取的大约4k,它通过检查堆栈或堆大小是否超过给予每个页面的页数来确保保护.我什么时候创建两个变量
char *s = (char *) malloc(100);
char sa[100];
Run Code Online (Sandbox Code Playgroud)
在一个for循环中,我可以s[i] = 'c';在它出现内存错误之前写入近4000次,而使用sa[i] = 'c';EDIT:我得到一个segmentation fault或stack smashing大于数组大小的错误.
我可以理解在第一种情况下有一个页面错误,它看到没有更多的页面被分配给堆,因此存在内存冲突.但是在第二种情况下会发生什么事情,gcc会在运行时为所有预分配的变量进行检查?
编辑:我发布下面的整个代码
int main(int argc,char* argv[]){
char *s = (char *) malloc(20);
char sa[400] = {0};
int i ,count;
printf(" enter the number of chars to write: ");
scanf("%d",&count);
for (i=0;i<count;i++){
printf("%d\n",i);
sa[i] = 'a';
//s[i] = 'a';
}
free(s);
}
Run Code Online (Sandbox Code Playgroud)
在许多 32 位操作系统上,堆栈向下增长。您只在数组中使用正索引,因此这取决于函数调用的嵌套深度。当您从数组中建立索引时,您将首先覆盖金丝雀。所以堆栈粉碎错误是第一个。接下来,您将开始覆盖函数参数和返回地址。如果没有金丝雀,这将导致函数返回跳转到nevernever land,通常会产生段错误。并非总是如此,它可能会意外地落在有效代码上,即堆栈缓冲区溢出攻击背后的逻辑。
当您继续前进时,您最终将越过堆栈顶部写入未分配的页面。然后出现段错误。在一个很少有快速发生的嵌套调用的小型测试程序中,会产生或消耗几千字节的数据。
也可以尝试使用负偏移量。这可以持续一段时间,不会造成任何意外,因为您正在写入未分配的堆栈空间。当您写入超过分配的堆栈大小(通常为兆字节)时,就会出现段错误。在 Windows 上,您将触发堆栈保护页面,生成一个异常,该异常就是为此站点命名的。