3

スタック ポインターへのアクセス時にセグメンテーション エラーが発生するプロセスをデバッグしようとしています。

main() の最初の行の前に segfault に使用されていたプロセス { では、segfault は行の別の場所に移動しました。

クラッシュしない場合、プロセスは無期限に正しく実行され続けます。

これは、プロセスがインスタンス化される方法に関連していると推測しています。

pid_t COsAbstraction::Start(const uint32_t coreId, const char* argv[])
{
    pid_t pid;
    sigset_t mask;
    sigset_t save;

    /*
     * Block SIGCHLD
     */
    sigemptyset(&mask);
    sigaddset(&mask, SIGCHLD);
    pthread_sigmask(SIG_BLOCK, &mask, &save);

    pid = fork();
    if(pid < 0)
    {
        _exit(false);
    }
    if (pid != 0)
    {
        // I am the parent
        pthread_sigmask(SIG_UNBLOCK, &save, NULL);
        return pid;;
    }
    // I am the child
    // Replace myself with the desired process
    execvp(argv[ 0 ],  const_cast<char**>(argv))

    _exit(0);

}

クラッシュ コード (散発的):

(gdb) disassemble 
Dump of assembler code for function main:
0x0804c663 <main+0>:    lea    0x4(%esp),%ecx
0x0804c667 <main+4>:    and    $0xfffffff0,%esp
0x0804c66a <main+7>:    pushl  -0x4(%ecx)
0x0804c66d <main+10>:   push   %ebp
0x0804c66e <main+11>:   mov    %esp,%ebp
0x0804c670 <main+13>:   push   %edi
0x0804c671 <main+14>:   push   %esi
0x0804c672 <main+15>:   push   %ebx
0x0804c673 <main+16>:   push   %ecx
0x0804c674 <main+17>:   sub    $0x525a8,%esp
0x0804c67a <main+23>:   call   0x804a22e <__i686.get_pc_thunk.bx>
0x0804c67f <main+28>:   add    $0x6125,%ebx
0x0804c685 <main+34>:   mov    (%ecx),%eax
0x0804c687 <main+36>:   mov    %eax,-0x52578(%ebp)
0x0804c68d <main+42>:   mov    0x4(%ecx),%ecx
0x0804c690 <main+45>:   mov    %ecx,-0x5257c(%ebp)
0x0804c696 <main+51>:   movl   $0x0,-0x418(%ebp)
0x0804c6a0 <main+61>:   movl   $0x400,0x8(%esp)
0x0804c6a8 <main+69>:   movl   $0x0,0x4(%esp)
0x0804c6b0 <main+77>:   lea    -0x410(%ebp),%eax
0x0804c6b6 <main+83>:   mov    %eax,(%esp)
0x0804c6b9 <main+86>:   call   0x8049c4c <memset@plt>

(gdb) info registers 
eax            0xf746d564       -146352796
ecx            0xf746d4e0       -146352928
edx            0xf746d500       -146352896
ebx            0x444a7ff4       1145733108
esp            0xf741af10       0xf741af10
ebp            0xf746d4c8       0xf746d4c8
esi            0x8050b30        134548272
edi            0x8049d90        134520208
eip            0x804c67a        0x804c67a <main+23>
eflags         0x210282 [ SF IF RF ID ]
cs             0x23     35
ss             0x2b     43
ds             0x2b     43
es             0x2b     43
fs             0x0      0

このコードは、24 コアの RedHat Linux 2.6 デバイスで実行されます。

アップデート:

クラッシュは呼び出しプロセスに関連していないことが判明しました! シェルから何百回も実行すると、単純な「hello world」もクラッシュします。

#include <stdio.h>
int main(int argc, char* argv[])
{
    char a[100*1024];
    a[0] = '1';
    printf("Hello There!\n");
    return 0;
}

新しい質問を送信するか、この質問を変更する必要がありますか?

4

1 に答える 1

0

プログラムのスタックから抜けようとしているために、C プログラムがクラッシュします。

ポイントは、次のような変数です

char a[100*1024];

スタックに割り当てられ、そのサイズは制限されており、配列の先頭を指すと、プロセスがスタックから終了します。

例を挙げると、私は amd64 を使用しているため、コードを変更しただけです。

#include <stdio.h>
int main(int argc, char* argv[])
{
    char a[12*1024*1024];
    a[0] = '1';
    printf("Hello There!\n");
    return 0;
}

そのため、スタックに 12 MB の変数を入れようとしています。ご覧のとおり、スタックのデフォルト サイズは 8MB で、実行しようとすると次のようになります。

ottavio@magritte:/tmp$ ulimit -s
8192
ottavio@magritte:/tmp$ ./x 
Segmentation fault

しかし、スタックサイズを大きくするとうまくいきます

ottavio@magritte:/tmp$ ulimit -s 16384
ottavio@magritte:/tmp$ ./x 
Hello There!
ottavio@magritte:/tmp$
于 2012-12-11T16:07:54.233 に答える