Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在输入函数时输入SIGSEGV_C++_Linux_Gdb_Segmentation Fault - Fatal编程技术网

C++ 在输入函数时输入SIGSEGV

C++ 在输入函数时输入SIGSEGV,c++,linux,gdb,segmentation-fault,C++,Linux,Gdb,Segmentation Fault,刚输入函数时,什么会导致分段错误 输入的函数如下所示: 21: void eesu3(Matrix & iQ) 22: { 其中矩阵是一个结构。使用GDB运行时,回溯会产生: (gdb) backtrace #0 eesu3 (iQ=...) at /home/.../eesu3.cc:22 #1 ... GDB没有说明智商是什么。…就在那里。 这是什么原因造成的 GCC:(Ubuntu/Linaro 4.6.3-1ubuntu5)4.6.3 用-O3-g构建的程序 调用者

刚输入函数时,什么会导致分段错误

输入的函数如下所示:

21:  void eesu3(Matrix & iQ)
22:  {
其中
矩阵
是一个
结构
。使用GDB运行时,回溯会产生:

(gdb) backtrace 
#0  eesu3 (iQ=...) at /home/.../eesu3.cc:22
#1  ...
GDB没有说明智商是什么。
就在那里。 这是什么原因造成的

GCC:(Ubuntu/Linaro 4.6.3-1ubuntu5)4.6.3

-O3-g构建的程序

调用者的反应如下:

Matrix q;
// do some stuff with q
eesu3(q);
这里没什么特别的

我用valgrind重新运行程序:

valgrind --tool=memcheck --leak-check=yes --show-reachable=yes --num-callers=20 --track-fds=yes <prgname>
看起来它是一个损坏的堆栈

    Dump of assembler code for function eesu3( Matrix & ):
   0x00000000014c7640 <+0>: push   %rbp
   0x00000000014c7641 <+1>: mov    %rsp,%rbp
   0x00000000014c7644 <+4>: push   %r15
   0x00000000014c7646 <+6>: push   %r14
   0x00000000014c7648 <+8>: push   %r13
   0x00000000014c764a <+10>:    push   %r12
   0x00000000014c764c <+12>:    push   %rbx
   0x00000000014c764d <+13>:    and    $0xfffffffffffff000,%rsp
   0x00000000014c7654 <+20>:    sub    $0x99b000,%rsp
=> 0x00000000014c765b <+27>:    mov    %rdi,0xfd8(%rsp)
函数eesu3(矩阵&)的汇编程序代码转储: 0x00000000014c7640:推送%rbp 0x00000000014c7641:mov%rsp,%rbp 0x00000000014c7644:推送%r15 0x00000000014c7646:推送%r14 0x00000000014c7648:推送%r13 0x00000000014c764a:推送%r12 0x00000000014c764c:推送%rbx 0x00000000014c764d:和$0xFFFFFFFFF000,%rsp 0x00000000014c7654:子$0x99b000,%rsp =>0x00000000014c765b:mov%rdi,0xfd8(%rsp)
好的,让我们明确一点:矩阵的数据存在于堆中。它基本上持有一个指向数据的指针。结构很小,32字节。(刚刚检查)

现在,我用不同的优化选项重建了程序:

-O0
:错误不会显示

-O1
:显示错误

-O3
:显示错误

--更新

-O3-fno inline-fno inline函数
:错误不会显示

这就解释了。函数的内联线过多导致堆栈使用过度


问题是由于堆栈溢出造成的。如果是矩阵,请检查您试图访问的索引。也许您正在访问超出矩阵对象维度的元素

刚输入函数时,什么会导致分段错误

最常见的原因是堆栈耗尽。在碰撞点执行
(gdb)disas
。如果崩溃的指令是
%rsp
递减后对堆栈位置的第一次读写,那么堆栈耗尽几乎肯定是原因

解决方案通常包括创建具有较大堆栈的线程,将一些较大的变量从堆栈移动到堆栈,或者两者兼而有之

另一个可能的原因是:如果
Matrix
包含非常大的数组,则不能将其放在堆栈上:内核不会将堆栈扩展到当前之外超过128K(或者说,我不记得确切的值)。若
矩阵
大于该限制,则不能将其放在堆栈上

更新:

   0x00000000014c7654 <+20>:    sub    $0x99b000,%rsp
=> 0x00000000014c765b <+27>:    mov    %rdi,0xfd8(%rsp)
0x00000000014c7654:sub$0x99b000,%rsp
=>0x00000000014c765b:mov%rdi,0xfd8(%rsp)
此拆解确认了诊断

此外,在堆栈上保留0x99b000字节(几乎是10MB)。在
eesu3
例程中,您必须在堆栈上找到一些巨大的对象。不要那样做

您所说的“内核不会将堆栈扩展到当前堆栈之外超过”是什么意思

当您将堆栈(递减
%rsp
)扩展例如1MB,然后尝试触摸该堆栈位置时,内存将无法访问(内核按需增长堆栈)。这将生成一个硬件陷阱,并将控制权转移到内核。当内核决定做什么时,它会查看

  • 当前
    %rsp
  • Meemory应用程序试图访问的位置
  • 当前线程的堆栈限制
  • 如果故障地址低于当前的
    %rsp
    ,但在128K(或其他类似大小的常数)之内,内核只会扩展堆栈(前提是这种扩展不会超过堆栈限制)

    如果故障地址比当前的
    %rsp
    低128K以上(这里的情况似乎就是这样),您将得到
    SIGSEGV

    这对于大多数程序来说都很好:即使它们在递归过程中使用了大量堆栈,它们通常也会以小块的形式扩展堆栈。但一个试图在一个例程中保留所有堆栈的等效程序可能会崩溃

    无论如何,在崩溃点执行
    (gdb)info locals
    ,并查看哪些locals可能需要10MB的堆栈。然后将它们移到堆中

    更新2:

    没有本地人

    啊,这个程序可能还没有发展到足够的程度,进入
    eesu3
    ,这样就不会有本地人了

    使用-O0构建时,错误消失。GCC错误

    这可能是一个GCC错误,但更可能的是GCC正在将许多其他例程内联到
    eesu3
    ,并且每个内联例程都需要自己的N KBs堆栈。如果使用
    -fno inline
    构建包含
    eesu3
    的源代码,问题是否会消失


    不幸的是,对此类行为进行分类并找出适当的解决方法,或修复GCC,需要编译器的专业知识。您可以从使用
    -fdump tree all
    编译并查看生成的
    *t.*
    文件开始。其中包含编译过程各个阶段的GCC内部表示的文本转储。您可能对它有足够的了解,以便取得进一步的进展。

    这是堆栈溢出。

    eesu3
    尝试在堆栈上分配非常大的内容,这可以在其汇编代码中看到:

    sub    $0x99b000,%rsp
    
    这意味着将消耗超过10MB的堆栈空间。

    问题可能出现在
    eesu3
    或它调用的a函数中,并且编译器选择内联。

    我的猜测是,问题出在函数
    eesu3
    调用中,而不是在测试(调试函数?)的情况下
    我想这是因为没有优化它是不会发生的-有了优化,函数内联到
    eesu3
    ,因此
    eesu3
    使用了大量堆栈。没有它,函数不是内联的,因此只有在实际调用时才会出现问题

    sub    $0x99b000,%rsp
    
    void eesu3(Matrix & iQ)
    
    char * buffer[268435456];
    
    void * pvBuffer = malloc(268435456);