- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在调用makecontext
之前,为什么我们需要设置堆栈大小ss_size
?
我刚刚有一个针对 makecontext/swapcontext
代码段的单元测试用例,它因 SIGSEGV
而失败。发生的事情是堆栈大小太小,不相关的内存(碰巧是一些独特的指针)被损坏并报告了段错误。所以段错误是在这些不相关的指针上,我本可以有例如一些字符串,然后内存损坏将不会被注意到。
我原以为 SIGSEGV
会在堆栈大小 ss_size
不足时立即引发,但是考虑到上述内存损坏,我得出结论,不可能从此处的 SIGSEGV
恢复。这让我回到了这个问题,为什么我们需要首先设置堆栈大小,当它没有被用来发出溢出信号时?它有什么用?
编辑:
嗯,这都是关于 makecontext(3) 的.这些函数仍在用于绿色线程、协程等。考虑到这些任务(在我看来)也不在 c++ 中,只是没有真正的替代品。
ss_size
在 sigaltstack(2) 中定义在 getcontext(3) 中定义的 ucontext_t
中需要 uc_stack
.
关注 minimal verifiable example如上所述,通过“绘制”内存显示内存损坏。
#include <iostream>
#include <ucontext.h>
#include <memory>
#include <cstring>
#include <stdio.h>
#include <unistd.h>
ucontext_t caller, callee;
void cb(void){
//paint stack with 2
char tmp[7000];
std::memset(tmp,2,7000);
//note stack size specified 6k bytes in size
//this should not be allowed.
//furthermore there is not even some signal raised here
//i expected raised SIGSEGV when this call stack exceeds ss_size
//it makes ss_size useless no?
}
int main(){
//
std::memset(&caller,0,sizeof(caller));
std::memset(&callee,0,sizeof(callee));
//create stack and paint 0
std::unique_ptr<std::byte[]> stack(new std::byte[10000]());
std::memset(stack.get(),0,10000);//paint stack 0
//make context
//note stack specified to [2000,8000)
//that means [0,2000) and [8000,10000) should not be touched
if(getcontext(&callee) == -1) {std::cout << errno << ":" << std::strerror(errno) << std::endl; return 1;}
callee.uc_link = &caller;
callee.uc_stack.ss_sp = stack.get()+2000;
callee.uc_stack.ss_size = 6000; //what is this line good for, what is it guarding?
makecontext(&callee,cb,0);
//swap to callee
if(swapcontext(&caller,&callee) == -1) {std::cout << errno << ":" << std::strerror(errno) << std::endl; return 1;}
//print color - should be 0
//if 2 then memory corrupted by callee
std::cout << int(stack[996]) << std::endl;
std::cout << int(stack[997]) << std::endl;
std::cout << int(stack[998]) << std::endl;
std::cout << int(stack[999]) << std::endl;
return 0;
}
再一次,我不明白的是为什么我们需要设置堆栈大小 ss_size
,因为它看起来没有被用来防止内存损坏或其他任何事情。看起来它只是在那里,但没有任何用处。但是我不敢相信它没有用。那么它“守卫”/有什么用呢?
好吧,我不想给这个问题带来更多的困惑。目标是通过安装 SIGSEGV
信号处理程序来恢复,从而摆脱固定大小的函数调用堆栈,但由于内存损坏,这看起来像是不可能完成的任务;或者有一个可增长的堆栈,例如使用 mmap(2)带有 MAP_GROWSDOWN
标志,但这看起来是 broken因此不是一个选择。
最佳答案
callee.uc_stack.ss_size = 6000; // what is this line good for, what is it guarding?
此行集是堆栈大小(如您在 man sigalstack 中所读)。来自阅读makecontext from glibc ss_size
用于确定堆栈结束,其中 glibc setups the stack的新语境。因为某些机器上的堆栈“向数字较低的地址增长”(就像它在 x86 architecture 和 wiki x86 上所做的那样),makecontext
需要/想要将它的数据放在堆栈的末尾。所以它需要确定堆栈的末尾,这就是 ss_size
的用途。
将 ss_size
设置为任何值并不意味着溢出堆栈大小将向您的进程发出操作系统信号,通知您的进程试图访问受限内存区域. *context
的实现不是(也不应该)设计为将地址 ss_sp + ss_size (+ 1)
作为内核保护内存,因此写入该地址将触发段错误。这仍然是所有正常变量。与写入未知内存位置(例如溢出数组)一样,无效地址可能恰好在您的进程地址空间内,因此根据内核,进程将在其地址空间内写入一切都很好。正如您在此处所做的那样 - 您的 cb
函数写入 new std::byte[10000]
内存,从内核的角度来看,这没有任何问题。
您很可能可以分配 new std::byte[6000]
并在 valgrind 或 gdb 或其他工具下运行您的进程以检查恶意写入。
关于c++ - 考虑 makecontext() 什么是 uc_stack.ss_size 好?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59167321/
作为我任务的一部分,我一直在实现一个用户线程库。我不明白 makecontext 函数: makecontext(&(mainthread->threadctx),(void(*)(void))sta
我的问题与这一行有关: int f = makecontext( &threadList[ numThreads ].context 我的程序在没有赋值操作的情况下编译没有错误,但根本无法运行
我的程序包含以下行: makecontext( &threadList[ numThreads ].context, (void (*)(void)) &threadStart, 1, 5); 其中
我需要实现一个库来使用 C 语言的线程。用户应该传递线程的函数及其参数,然后我需要为其处理和创建线程。这是添加新线程的函数: int add_thread(void (*func)(int),
这个问题在这里已经有了答案: 关闭 11 年前。 我想按如下方式将变量参数传递给 makecontext 函数。 void a(...) { .... makecontext( &stack,
我正在尝试制作一个像 pthreads 这样的用户级线程库。我正在使用 makecontext()/swapcontext() 在线程之间进行切换,并在为线程创建上下文时传递 uctx_main 到上
我正在研究 C 编程中的上下文切换,并在 Internet 上找到了以下示例代码。我试图弄清楚是否只有 makecontext() 函数可以触发执行某些操作的函数。 setcontext()、getc
makecontext 的手册页声明 argc 之后的参数应该仅为 integer(int): ...the function func is called, and passed the serie
我看到了一些关于用户线程库的问题,但似乎没有一个能回答我的问题。我能够创建线程、运行它们、取消它们以及退出它们。由于某种原因我不能做的是让线程返回数据。 当我初始化我的线程库时,我将我的退出线程上下文
在another question我在移植代码时遇到了问题: unsigned long stack[] = { 1, 23, 33, 43 }; /* save all the registers
来自 makecontext() 手册... Due to limitations in the current pthread implementation, makecontext should
我对上下文切换很感兴趣。我已将示例代码复制到文件中 http://pubs.opengroup.org/onlinepubs/009695399/functions/makecontext.html
在 unix 环境中,makecontext()/swapcontext() 函数系列有时用于在 C 中实现协程。然而,这些函数直接操作堆栈和执行流。当从 C 切换到 C++ 时,这些低级功能通常有很
在调用makecontext之前,为什么我们需要设置堆栈大小ss_size? 我刚刚有一个针对 makecontext/swapcontext 代码段的单元测试用例,它因 SIGSEGV 而失败。发生
我已成功使用 makecontext/swapcontext 移动堆栈。但是,当我尝试将它与 pthread_mutex_lock 或 pthread_mutex_unlock 一起使用时,我总是
我无法将 C++0x lambda 函数作为第二个参数传递给 makecontext(来自 ucontext.h)。 makecontext 的签名是: void makecontext(uconte
#include #include #define _XOPEN_SOURCE 600 #include /* Tests creation. Should print "Hello Wo
我是一名优秀的程序员,十分优秀!