1

関数呼び出しのスタックを変更できる次のコードを書いています。しかし、それは常にprintfでsegfaultに遭遇します。コードをアセンブリでデバッグしたところ、スタックが正常に切り替えられました。segfault を作成したのは printf ステートメントであり、理由は不明です。誰が私がもっと調べるべき方向性を知っていますか?

ありがとう。

char stack[4000000*4]; 

void foo(int ad) {
    int i = 100;
    int sum = i*i + ad;
    printf("stack changed to %X\n", stack);
}

/* in this example, foo (and its decendents) live on a new stack */
void change_stack(void *newstack) {
    void *ctx[5]; // Jump buffer for setjmp/longjmp.
    if (0 == __builtin_longjmp(ctx)) {
        ctx[2] = newstack; // switch stack  
        __builtin_longjmp(ctx, 1);/* here stack is switched */
    } else {
    /* now live on new stack, can we pass parameters now ? */
    int ad = 20;
    foo(ad);
    }
}

int main (int argc, char** argv)
{
  int i = 10;
  change_stack(stack);
  printf("return, %d\n", i);
  return 0;
}
4

2 に答える 2

2

古いスタックの内容をコピーせずにスタックを切り替えます。返されるときchange_stack、結果は未定義です (たとえば、 address にジャンプしNULLてセグメンテーション違反が発生する可能性があります)。また、ローカル変数なども未定義になります。

また、(ここでは x86 について話していると仮定して)、スタック ポインターはプッシュ時にデクリメントされます。割り当てた新しいスタック ポインターは配列のベース (最下位) アドレスであるためstack、プッシュすると、この配列の外側のポインターが減少し、segfault が発生する可能性もあります。

于 2013-07-23T21:02:08.713 に答える