在处理ucontext时,为什么打印到stderr会导致分段错误?

在处理ucontext时,为什么打印到stderr会导致分段错误?,c,posix,ucontext,C,Posix,Ucontext,我在为一门操作系统课程做一个项目。任务是实现一个处理线程的库,类似于pthreads,但要简单得多。其目的是练习调度算法。最终产品是一个.a文件。课程结束了,一切正常(就功能而言) 不过,我对自己面临的一个问题感到好奇。在源文件的三个不同函数上,如果添加以下行,例如: fprintf(stderr, "My lucky number is %d\n", 4); 我有一个分割错误。如果改用stdout,或者如果格式不包含任何变量,则不会发生同样的情况 这给我留下了两个主要问题: 为什么它只发生在

我在为一门操作系统课程做一个项目。任务是实现一个处理线程的库,类似于
pthreads
,但要简单得多。其目的是练习调度算法。最终产品是一个
.a
文件。课程结束了,一切正常(就功能而言)

不过,我对自己面临的一个问题感到好奇。在源文件的三个不同函数上,如果添加以下行,例如:

fprintf(stderr, "My lucky number is %d\n", 4);
我有一个分割错误。如果改用
stdout
,或者如果格式不包含任何变量,则不会发生同样的情况

这给我留下了两个主要问题:

  • 为什么它只发生在我代码的三个函数中,而不发生在其他函数中

  • 使用
    getcontext()
    makecontext()
    创建上下文,或者使用
    setcontext()
    swapcontext()
    更改上下文是否会弄乱标准文件描述符

  • 我的直觉是,这些功能可能是造成这种情况的原因。更重要的是,当我的代码中发生这种情况的三个函数都具有代码其他部分切换到的上下文时。通常通过
    setcontext()
    ,但
    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_上下文的在线示例。

    假设使用glibc,解释是
    fprintf
    带有无缓冲流(例如默认情况下
    stderr
    )在内部创建一个大小为
    BUFSIZE
    字节的堆栈上缓冲区。请参见
    stdio common/vfprintf.c
    中的函数
    buffered_vfprintf
    BUFSIZ
    是8192,因此您最终会出现堆栈溢出,因为您创建的堆栈太小。

    我猜您可能有某种形式的内存损坏或争用情况;这通常是添加或删除看似无害的行导致错误的原因。
    STACK\u SIZE
    的值是多少?
    STACK\u SIZE
    的值是8192字节。另外,
    context\u end
    的创建方式与此非常相似。@YuriJ:这可能不足以调用
    fprintf
    函数。您使用的是什么操作系统(如果是Linux,那么是什么libc?@YuriJ,尝试解决这些漏洞。您可能会发现一个bug!