为什么我在这里遇到分段错误?

时间:2012-01-04 16:43:27

标签: c linux gcc x86 pthreads

我有以下代码,我尝试在堆栈中写入内容。我写在堆栈的底部,应用程序仍然没有触及(注意堆栈向下增长, stackaddr 在这里指向底部)。

然而,即使在执行 mprotect 以向该内存区域提供写入和读取权限之后,我也会出现分段错误。即使我使用编译标志 -fno-stack-protector ,我也会出现分段错误。这里发生了什么?

pthread_attr_t attr;
void * stackaddr;
int * plocal_var;
size_t stacksize;

pthread_getattr_np(pthread_self(), &attr);
pthread_attr_getstack( &attr, &stackaddr, &stacksize );

printf( "stackaddr = %p, stacksize = %d\n", stackaddr, stacksize );

plocal_var = (int*)stackaddr;
mprotect((void*)plocal_var, 4096, PROT_READ | PROT_WRITE);
*plocal_var = 4;
printf( "local_var = %d!\n", *plocal_var );

1 个答案:

答案 0 :(得分:3)

您几乎肯定会尝试mprotect()尚未映射的页面。您应该检查返回代码:mprotect()可能返回-1并将errno设置为ENOMEM(这在mprotect(2) man page中有记录)。

堆栈页面是按需映射的,但是内核足够聪明,可以区分由当前堆栈指针处或之上的访问引起的页面错误(这是由向下扩展堆栈的有效尝试引起的,通过递减堆栈指针,然后执行读取或写入新值的某些正偏移量),以及由堆栈指针下方的访问引起的页面错误(无效)。