3

我正在尝试调试一个进程,该进程偶尔会在访问堆栈指针时出现分段错误。

用于在 main() 的第一行之前进行段错误的进程 { 现在段错误移动到该行的另一个位置。

如果它没有崩溃,那么该过程将无限期地继续正确运行。

我猜这与进程实例化的方式有关:

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”在 shell 执行数百次时也会崩溃:

#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 回答