c - 为什么在处理ucontext时打印到stderr会导致分段错误?
问题描述
我正在为操作系统课程做一个项目。任务是实现一个用于处理线程的库,类似于pthreads
,但要简单得多。它的目的是练习调度算法。最终产品是一个.a
文件。课程结束了,一切正常(就功能而言)。
不过,我对我遇到的一个问题感到好奇。在我的源文件的三个不同函数上,如果我添加以下行,例如:
fprintf(stderr, "My lucky number is %d\n", 4);
我得到一个分段错误。stdout
如果改为使用,或者格式不包含任何变量,则不会发生同样的情况。
这给我留下了两个主要问题:
为什么它只发生在我的代码的三个函数中,而不是其他函数?
getcontext()
是否可以使用and创建上下文,或者使用标准文件描述符makecontext()
更改上下文?setcontext()
swapcontext()
我的直觉说这些功能可能是造成这种情况的原因。考虑到发生这种情况的代码的三个函数是具有代码其他部分切换到的上下文的函数,甚至更多。通常 bysetcontext()
用于swapcontext()
进入调度程序,用于选择另一个线程来执行。
此外,如果是这种情况,那么:
- 使用这些函数创建线程的正确方法是什么?
我目前正在执行以下操作:
/*------------------------------------------------------------------------------
Funct: Creates an execution context for the function and arguments passed.
Input: uc -> Pointer where the context will be created.
funct -> Function to be executed in the context.
arg -> Argument to the function.
Return: If the function succeeds, 0 will be returned. Otherwise -1.
------------------------------------------------------------------------------*/
static int create_context(ucontext_t *uc, void *funct, void *arg)
{
if(getcontext(uc) != 0) // Gets a context "model"
{
return -1;
}
stack_t *sp = (stack_t*)malloc(STACK_SIZE); // Stack area for the execution context
if(!sp) // A stack area is mandatory
{
return -1;
}
uc->uc_stack.ss_sp = sp; // Sets stack pointer
uc->uc_stack.ss_size = STACK_SIZE; // Sets stack size
uc->uc_link = &context_end; // Sets the context to go after execution
makecontext(uc, funct, 1, arg); // "Makes everything work" (can't fail)
return 0;
}
这段代码可能稍作修改,但它最初是一个关于如何使用 u_context 的在线示例。
解决方案
假设 glibc,解释是fprintf
使用无缓冲流(例如stderr
默认情况下)在内部创建一个堆栈缓冲区,其大小为BUFSIZE
字节。请参阅 中的 函数buffered_vfprintf
。是 8192,所以你最终会出现堆栈溢出,因为你创建的堆栈太小了。stdio-common/vfprintf.c
BUFSIZ
推荐阅读
- uiimagepickercontroller - 在 iOS 14.2 中使用相机录制视频时显示黑屏
- java - 如何将后端的图像直接写入图像标签的 src 属性?
- r - 用 R 估计 1850 年到 1950 年间每一年的存活人数
- visual-studio-code - 为什么`dae`命令会删除文件中的所有内容?
- c++ - 编译器不会在代码块中编译 graphics.h
- html - 如何使我的复选框在表单中对齐?
- python - 错误:Series 的真值不明确。使用 a.empty、a.bool()、a.item()、a.any() 或 a.all()。无法更新数据框列
- c# - 在抽象类的构造函数中调用抽象方法
- xcode - 'git初始化-b
' 终端中的命令引发“未知开关”错误 - javascript - Expo React Native WebView 在 Android 上的应用中打开谷歌地图