setcontext()中的Stackoverflow

时间:2014-10-17 07:55:52

标签: c multithreading process stack-overflow

以下是我在Wikipedia上看到的代码。这会导致堆栈溢出吗?

#include <stdio.h>
#include <ucontext.h>
#include <unistd.h>

int main(int argc, const char *argv[]){
    ucontext_t context;

    getcontext(&context);
    puts("Hello world");
    sleep(1);
    setcontext(&context);
    return 0;
}

原因:当代码到达setcontext()时,它会在堆栈上推送新帧。由于setcontext()没有返回,它的推帧将保持堆叠状态。并且由于程序处于无限循环中,它继续在堆栈上推送新帧,导致堆栈溢出。

2 个答案:

答案 0 :(得分:2)

gdb否则说:

(gdb) list
1   #include <stdio.h>
2   #include <ucontext.h>
3   #include <unistd.h>
4   
5   int main(int argc, const char *argv[]){
6       ucontext_t context;
7   
8       getcontext(&context);
9       puts("Hello world");
10      //sleep(1);
(gdb) break 9
Breakpoint 1 at 0x4005bb: file test.c, line 9.
(gdb) run
Starting program: /home/dtarcatu/workspace/ctest/test 

Breakpoint 1, main (argc=1, argv=0x7fffffffe008) at test.c:9
9       puts("Hello world");
(gdb) print $rbp
$1 = (void *) 0x7fffffffdf20
(gdb) print $rsp
$2 = (void *) 0x7fffffffdb60
(gdb) c
Continuing.
Hello world

Breakpoint 1, main (argc=1, argv=0x7fffffffe008) at test.c:9
9       puts("Hello world");
(gdb) print $rbp
$3 = (void *) 0x7fffffffdf20
(gdb) print $rsp
$4 = (void *) 0x7fffffffdb60
(gdb) c
Continuing.
Hello world

Breakpoint 1, main (argc=1, argv=0x7fffffffe008) at test.c:9
9       puts("Hello world");
(gdb) print $rbp
$5 = (void *) 0x7fffffffdf20
(gdb) print $rsp
$6 = (void *) 0x7fffffffdb60

我不熟悉这些上下文处理函数,但似乎setcontext不会将新帧推送到堆栈,而是完全按照它的方式恢复堆栈。所以你最终会陷入无限循环 - 没有堆栈溢出......

答案 1 :(得分:1)

setcontext会将堆栈返回到getcontext处的状态。

当您调用setcontext时,新的堆栈帧将被推送到堆栈。然后,setcontext会将堆栈恢复为getcontext的查看方式,从而有效地移除框架。

因此程序确实创建了一个无限循环,但它不会导致堆栈溢出。