简体   繁体   English

检测到堆栈粉碎

[英]Stack smashing detected

I am executing my a.out file.我正在执行我的 a.out 文件。 After execution the program runs for some time then exits with the message:执行后程序运行一段时间然后退出并显示消息:

**** stack smashing detected ***: ./a.out terminated*
*======= Backtrace: =========*
*/lib/tls/i686/cmov/libc.so.6(__fortify_fail+0x48)Aborted*

What could be the possible reasons for this and how do I rectify it?这可能是什么原因,我该如何纠正?

Stack Smashing here is actually caused due to a protection mechanism used by gcc to detect buffer overflow errors.这里的Stack Smashing其实是gcc用来检测缓冲区溢出错误的保护机制造成的。 For example in the following snippet:例如在以下代码段中:

#include <stdio.h>

void func()
{
    char array[10];
    gets(array);
}

int main(int argc, char **argv)
{
    func();
}

The compiler, (in this case gcc) adds protection variables (called canaries) which have known values.编译器(在本例中为 gcc)添加具有已知值的保护变量(称为金丝雀)。 An input string of size greater than 10 causes corruption of this variable resulting in SIGABRT to terminate the program.大小大于 10 的输入字符串会导致此变量损坏,从而导致 SIGABRT 终止程序。

To get some insight, you can try disabling this protection of gcc using option -fno-stack-protector while compiling.要获得一些见解,您可以尝试在编译时使用选项-fno-stack-protector禁用 gcc 的这种保护。 In that case you will get a different error, most likely a segmentation fault as you are trying to access an illegal memory location.在这种情况下,您将收到不同的错误,很可能是在您尝试访问非法内存位置时出现分段错误。 Note that -fstack-protector should always be turned on for release builds as it is a security feature.请注意,应始终为发布版本打开-fstack-protector ,因为它是一项安全功能。

You can get some information about the point of overflow by running the program with a debugger.您可以通过使用调试器运行程序来获取有关溢出点的一些信息。 Valgrind doesn't work well with stack-related errors, but like a debugger, it may help you pin-point the location and reason for the crash. Valgrind 不能很好地处理与堆栈相关的错误,但就像调试器一样,它可以帮助您确定崩溃的位置和原因。

Minimal reproduction example with disassembly analysis带有拆卸分析的最小复制示例

main.c主文件

void myfunc(char *const src, int len) {
    int i;
    for (i = 0; i < len; ++i) {
        src[i] = 42;
    }
}

int main(void) {
    char arr[] = {'a', 'b', 'c', 'd'};
    int len = sizeof(arr);
    myfunc(arr, len + 1);
    return 0;
}

GitHub upstream . GitHub 上游.

Compile and run:编译并运行:

gcc -fstack-protector-all -g -O0 -std=c99 main.c
ulimit -c unlimited && rm -f core
./a.out

fails as desired:根据需要失败:

*** stack smashing detected ***: terminated
Aborted (core dumped)

Tested on Ubuntu 20.04, GCC 10.2.0.在 Ubuntu 20.04、GCC 10.2.0 上测试。

On Ubuntu 16.04, GCC 6.4.0, I could reproduce with -fstack-protector instead of -fstack-protector-all , but it stopped blowing up when I tested on GCC 10.2.0 as per Geng Jiawen's comment .在 Ubuntu 16.04、GCC 6.4.0 上,我可以使用-fstack-protector而不是-fstack-protector-all复制,但是根据耿嘉文的评论,当我在 GCC 10.2.0 上进行测试时,它停止了。 man gcc clarifies that as suggested by the option name, the -all version adds checks more aggressively, and therefore presumably incurs a larger performance loss: man gcc澄清,正如选项名称所建议的, -all版本更积极地添加检查,因此可能会导致更大的性能损失:

-fstack-protector -fstack-protector

Emit extra code to check for buffer overflows, such as stack smashing attacks.发出额外的代码来检查缓冲区溢出,例如堆栈粉碎攻击。 This is done by adding a guard variable to functions with vulnerable objects.这是通过向具有易受攻击对象的函数添加保护变量来完成的。 This includes functions that call "alloca", and functions with buffers larger than or equal to 8 bytes.这包括调用“alloca”的函数,以及缓冲区大于或等于 8 字节的函数。 The guards are initialized when a function is entered and then checked when the function exits.守卫在进入函数时初始化,然后在函数退出时检查。 If a guard check fails, an error message is printed and the program exits.如果防护检查失败,则会打印错误消息并退出程序。 Only variables that are actually allocated on the stack are considered, optimized away variables or variables allocated in registers don't count.仅考虑实际分配在堆栈上的变量,优化掉的变量或分配在寄存器中的变量不计算在内。

-fstack-protector-all -fstack-protector-all

Like -fstack-protector except that all functions are protected.与 -fstack-protector 类似,只是所有功能都受到保护。

Disassembly拆卸

Now we look at the disassembly:现在我们看看反汇编:

objdump -D a.out

which contains:其中包含:

int main (void){
  400579:       55                      push   %rbp
  40057a:       48 89 e5                mov    %rsp,%rbp

  # Allocate 0x10 of stack space.
  40057d:       48 83 ec 10             sub    $0x10,%rsp

  # Put the 8 byte canary from %fs:0x28 to -0x8(%rbp),
  # which is right at the bottom of the stack.
  400581:       64 48 8b 04 25 28 00    mov    %fs:0x28,%rax
  400588:       00 00 
  40058a:       48 89 45 f8             mov    %rax,-0x8(%rbp)

  40058e:       31 c0                   xor    %eax,%eax
    char arr[] = {'a', 'b', 'c', 'd'};
  400590:       c6 45 f4 61             movb   $0x61,-0xc(%rbp)
  400594:       c6 45 f5 62             movb   $0x62,-0xb(%rbp)
  400598:       c6 45 f6 63             movb   $0x63,-0xa(%rbp)
  40059c:       c6 45 f7 64             movb   $0x64,-0x9(%rbp)
    int len = sizeof(arr);
  4005a0:       c7 45 f0 04 00 00 00    movl   $0x4,-0x10(%rbp)
    myfunc(arr, len + 1);
  4005a7:       8b 45 f0                mov    -0x10(%rbp),%eax
  4005aa:       8d 50 01                lea    0x1(%rax),%edx
  4005ad:       48 8d 45 f4             lea    -0xc(%rbp),%rax
  4005b1:       89 d6                   mov    %edx,%esi
  4005b3:       48 89 c7                mov    %rax,%rdi
  4005b6:       e8 8b ff ff ff          callq  400546 <myfunc>
    return 0;
  4005bb:       b8 00 00 00 00          mov    $0x0,%eax
}
  # Check that the canary at -0x8(%rbp) hasn't changed after calling myfunc.
  # If it has, jump to the failure point __stack_chk_fail.
  4005c0:       48 8b 4d f8             mov    -0x8(%rbp),%rcx
  4005c4:       64 48 33 0c 25 28 00    xor    %fs:0x28,%rcx
  4005cb:       00 00 
  4005cd:       74 05                   je     4005d4 <main+0x5b>
  4005cf:       e8 4c fe ff ff          callq  400420 <__stack_chk_fail@plt>

  # Otherwise, exit normally.
  4005d4:       c9                      leaveq 
  4005d5:       c3                      retq   
  4005d6:       66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1)
  4005dd:       00 00 00 

Notice the handy comments automatically added by objdump 's artificial intelligence module .请注意objdump人工智能模块自动添加的方便注释。

If you run this program multiple times through GDB, you will see that:如果你通过 GDB 多次运行这个程序,你会看到:

  • the canary gets a different random value every time金丝雀每次都会得到不同的随机值
  • the last loop of myfunc is exactly what modifies the address of the canary myfunc的最后一个循环正是修改金丝雀地址的原因

The canary randomized by setting it with %fs:0x28 , which contains a random value as explained at:通过使用%fs:0x28设置它来随机化金丝雀,它包含一个随机值,解释如下:

Debug attempts调试尝试

From now on, we modify the code:从现在开始,我们修改代码:

    myfunc(arr, len + 1);

to be instead:改为:

    myfunc(arr, len);
    myfunc(arr, len + 1); /* line 12 */
    myfunc(arr, len);

to be more interesting.变得更有趣。

We will then try to see if we can pinpoint the culprit + 1 call with a method more automated than just reading and understanding the entire source code.然后,我们将尝试查看是否可以使用一种比仅阅读和理解整个源代码更自动化的方法来查明罪魁祸首+ 1调用。

gcc -fsanitize=address to enable Google's Address Sanitizer (ASan) gcc -fsanitize=address启用 Google 的地址清理程序 (ASan)

If you recompile with this flag and run the program, it outputs:如果使用此标志重新编译并运行程序,它会输出:

#0 0x4008bf in myfunc /home/ciro/test/main.c:4
#1 0x40099b in main /home/ciro/test/main.c:12
#2 0x7fcd2e13d82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
#3 0x400798 in _start (/home/ciro/test/a.out+0x40079

followed by some more colored output.其次是一些更多的彩色输出。

This clearly pinpoints the problematic line 12.这清楚地指出了有问题的第 12 行。

The source code for this is at: https://github.com/google/sanitizers but as we saw from the example it is already upstreamed into GCC.其源代码位于: https : //github.com/google/sanitizers但正如我们从示例中看到的那样,它已经上传到 GCC。

ASan can also detect other memory problems such as memory leaks: How to find memory leak in a C++ code/project? ASan 还可以检测其他内存问题,例如内存泄漏: 如何在 C++ 代码/项目中查找内存泄漏?

Valgrind SGCheck Valgrind SGCheck

As mentioned by others , Valgrind is not good at solving this kind of problem.正如其他人提到的,Valgrind 不擅长解决此类问题。

It does have an experimental tool called SGCheck :它确实有一个名为 SGCheck的实验工具:

SGCheck is a tool for finding overruns of stack and global arrays. SGCheck 是一种用于查找堆栈和全局数组溢出的工具。 It works by using a heuristic approach derived from an observation about the likely forms of stack and global array accesses.它的工作原理是使用启发式方法,该方法源自对堆栈和全局数组访问的可能形式的观察。

So I was not very surprised when it did not find the error:所以当它没有发现错误时我并没有很惊讶:

valgrind --tool=exp-sgcheck ./a.out

The error message should look like this apparently: Valgrind missing error错误消息显然应该是这样的: Valgrind missing error

GDB广交会

An important observation is that if you run the program through GDB, or examine the core file after the fact:一个重要的观察是,如果您通过 GDB 运行程序,或者事后检查core文件:

gdb -nh -q a.out core

then, as we saw on the assembly, GDB should point you to the end of the function that did the canary check:然后,正如我们在程序集上看到的,GDB 应该指向执行金丝雀检查的函数的末尾:

(gdb) bt
#0  0x00007f0f66e20428 in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:54
#1  0x00007f0f66e2202a in __GI_abort () at abort.c:89
#2  0x00007f0f66e627ea in __libc_message (do_abort=do_abort@entry=1, fmt=fmt@entry=0x7f0f66f7a49f "*** %s ***: %s terminated\n") at ../sysdeps/posix/libc_fatal.c:175
#3  0x00007f0f66f0415c in __GI___fortify_fail (msg=<optimized out>, msg@entry=0x7f0f66f7a481 "stack smashing detected") at fortify_fail.c:37
#4  0x00007f0f66f04100 in __stack_chk_fail () at stack_chk_fail.c:28
#5  0x00000000004005f6 in main () at main.c:15
(gdb) f 5
#5  0x00000000004005f6 in main () at main.c:15
15      }
(gdb)

And therefore the problem is likely in one of the calls that this function made.因此,问题可能出在此函数进行的调用之一中。

Next we try to pinpoint the exact failing call by first single stepping up just after the canary is set:接下来,我们尝试通过在金丝雀设置后第一次单步执行来确定确切的失败调用:

  400581:       64 48 8b 04 25 28 00    mov    %fs:0x28,%rax
  400588:       00 00 
  40058a:       48 89 45 f8             mov    %rax,-0x8(%rbp)

and watching the address:并查看地址:

(gdb) p $rbp - 0x8
$1 = (void *) 0x7fffffffcf18
(gdb) watch 0x7fffffffcf18
Hardware watchpoint 2: *0x7fffffffcf18
(gdb) c
Continuing.

Hardware watchpoint 2: *0x7fffffffcf18

Old value = 1800814336
New value = 1800814378
myfunc (src=0x7fffffffcf14 "*****?Vk\266", <incomplete sequence \355\216>, len=5) at main.c:3
3           for (i = 0; i < len; ++i) {
(gdb) p len
$2 = 5
(gdb) p i
$3 = 4
(gdb) bt
#0  myfunc (src=0x7fffffffcf14 "*****?Vk\266", <incomplete sequence \355\216>, len=5) at main.c:3
#1  0x00000000004005cc in main () at main.c:12

Now, this does leaves us at the right offending instruction: len = 5 and i = 4 , and in this particular case, did point us to the culprit line 12.现在,这确实让我们看到了正确的违规指令: len = 5i = 4 ,在这种特殊情况下,确实将我们指向了罪魁祸首第 12 行。

However, the backtrace is corrupted, and contains some trash.但是,回溯已损坏,并包含一些垃圾。 A correct backtrace would look like:正确的回溯如下所示:

#0  myfunc (src=0x7fffffffcf14 "abcd", len=4) at main.c:3
#1  0x00000000004005b8 in main () at main.c:11

so maybe this could corrupt the stack and prevent you from seeing the trace.所以也许这可能会破坏堆栈并阻止您看到跟踪。

Also, this method requires knowing what is the last call of the canary checking function otherwise you will have false positives, which will not always be feasible, unless you use reverse debugging .此外,此方法需要知道金丝雀检查功能的最后一次调用是什么,否则您将出现误报,这并不总是可行的,除非您使用反向调试

Please look at the following situation:请看以下情况:

ab@cd-x:$ cat test_overflow.c 
#include <stdio.h>
#include <string.h>

int check_password(char *password){
    int flag = 0;
    char buffer[20];
    strcpy(buffer, password);

    if(strcmp(buffer, "mypass") == 0){
        flag = 1;
    }
    if(strcmp(buffer, "yourpass") == 0){
        flag = 1;
    }
    return flag;
}

int main(int argc, char *argv[]){
    if(argc >= 2){
        if(check_password(argv[1])){
            printf("%s", "Access granted\n");
        }else{
            printf("%s", "Access denied\n");
        }
    }else{
        printf("%s", "Please enter password!\n");
    }
}
ab@cd-x:$ gcc -g -fno-stack-protector test_overflow.c 
ab@cd-x:$ ./a.out mypass
Access granted
ab@cd-x:$ ./a.out yourpass
Access granted
ab@cd-x:$ ./a.out wepass
Access denied
ab@cd-x:$ ./a.out wepassssssssssssssssss
Access granted

ab@cd-x:$ gcc -g -fstack-protector test_overflow.c 
ab@cd-x:$ ./a.out wepass
Access denied
ab@cd-x:$ ./a.out mypass
Access granted
ab@cd-x:$ ./a.out yourpass
Access granted
ab@cd-x:$ ./a.out wepassssssssssssssssss
*** stack smashing detected ***: ./a.out terminated
======= Backtrace: =========
/lib/tls/i686/cmov/libc.so.6(__fortify_fail+0x48)[0xce0ed8]
/lib/tls/i686/cmov/libc.so.6(__fortify_fail+0x0)[0xce0e90]
./a.out[0x8048524]
./a.out[0x8048545]
/lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe6)[0xc16b56]
./a.out[0x8048411]
======= Memory map: ========
007d9000-007f5000 r-xp 00000000 08:06 5776       /lib/libgcc_s.so.1
007f5000-007f6000 r--p 0001b000 08:06 5776       /lib/libgcc_s.so.1
007f6000-007f7000 rw-p 0001c000 08:06 5776       /lib/libgcc_s.so.1
0090a000-0090b000 r-xp 00000000 00:00 0          [vdso]
00c00000-00d3e000 r-xp 00000000 08:06 1183       /lib/tls/i686/cmov/libc-2.10.1.so
00d3e000-00d3f000 ---p 0013e000 08:06 1183       /lib/tls/i686/cmov/libc-2.10.1.so
00d3f000-00d41000 r--p 0013e000 08:06 1183       /lib/tls/i686/cmov/libc-2.10.1.so
00d41000-00d42000 rw-p 00140000 08:06 1183       /lib/tls/i686/cmov/libc-2.10.1.so
00d42000-00d45000 rw-p 00000000 00:00 0 
00e0c000-00e27000 r-xp 00000000 08:06 4213       /lib/ld-2.10.1.so
00e27000-00e28000 r--p 0001a000 08:06 4213       /lib/ld-2.10.1.so
00e28000-00e29000 rw-p 0001b000 08:06 4213       /lib/ld-2.10.1.so
08048000-08049000 r-xp 00000000 08:05 1056811    /dos/hacking/test/a.out
08049000-0804a000 r--p 00000000 08:05 1056811    /dos/hacking/test/a.out
0804a000-0804b000 rw-p 00001000 08:05 1056811    /dos/hacking/test/a.out
08675000-08696000 rw-p 00000000 00:00 0          [heap]
b76fe000-b76ff000 rw-p 00000000 00:00 0 
b7717000-b7719000 rw-p 00000000 00:00 0 
bfc1c000-bfc31000 rw-p 00000000 00:00 0          [stack]
Aborted
ab@cd-x:$ 

When I disabled the stack smashing protector no errors were detected, which should have happened when I used "./a.out wepassssssssssssssssss"当我禁用堆栈粉碎保护器时,没有检测到错误,当我使用“./a.out wepasssssssssssssssss”时应该会发生这种情况

So to answer your question above, the message "** stack smashing detected : xxx" was displayed because your stack smashing protector was active and found that there is stack overflow in your program.所以为了回答你上面的问题,显示消息“** stack smashing detection : xxx”是因为你的stack smashingprotector处于活动状态,发现你的程序中存在堆栈溢出。

Just find out where that occurs, and fix it.只需找出发生的位置,然后修复它。

You could try to debug the problem using valgrind :您可以尝试使用valgrind调试问题:

The Valgrind distribution currently includes six production-quality tools: a memory error detector, two thread error detectors, a cache and branch-prediction profiler, a call-graph generating cache profiler, and a heap profiler. Valgrind 发行版目前包括六个生产质量工具:一个内存错误检测器、两个线程错误检测器、一个缓存和分支预测分析器、一个调用图生成缓存分析器和一个堆分析器。 It also includes two experimental tools: a heap/stack/global array overrun detector , and a SimPoint basic block vector generator.它还包括两个实验工具:堆/堆栈/全局数组溢出检测器和 SimPoint 基本块向量生成器。 It runs on the following platforms: X86/Linux, AMD64/Linux, PPC32/Linux, PPC64/Linux, and X86/Darwin (Mac OS X).它在以下平台上运行:X86/Linux、AMD64/Linux、PPC32/Linux、PPC64/Linux 和 X86/Darwin (Mac OS X)。

这意味着您以非法方式写入堆栈上的某些变量,很可能是Buffer overflow的结果。

What could be the possible reasons for this and how do I rectify it?这可能是什么原因,我该如何纠正?

One scenario would be in the following example:一种情况是在以下示例中:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void swap ( char *a , char *b );
void revSTR ( char *const src );

int main ( void ){
    char arr[] = "A-B-C-D-E";

    revSTR( arr );
    printf("ARR = %s\n", arr );
}

void swap ( char *a , char *b ){
    char tmp = *a;
    *a = *b;
    *b = tmp;
}

void revSTR ( char *const src ){
    char *start = src;
    char *end   = start + ( strlen( src ) - 1 );

    while ( start < end ){
        swap( &( *start ) , &( *end ) );
        start++;
        end--;
    }
}

In this program you can reverse a String or a part of the string if you for example call reverse() with something like this:在此程序中,如果您使用以下内容调用reverse() ,您可以反转字符串或字符串的一部分:

reverse( arr + 2 );

If you decide to pass the length of the array like this:如果您决定像这样传递数组的长度:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void swap ( char *a , char *b );
void revSTR ( char *const src, size_t len );

int main ( void ){
    char arr[] = "A-B-C-D-E";
    size_t len = strlen( arr );

    revSTR( arr, len );
    printf("ARR = %s\n", arr );
}

void swap ( char *a , char *b ){
    char tmp = *a;
    *a = *b;
    *b = tmp;
}

void revSTR ( char *const src, size_t len ){
    char *start = src;
    char *end   = start + ( len - 1 );

    while ( start < end ){
        swap( &( *start ) , &( *end ) );
        start++;
        end--;
    }
}

Works fine too.也能正常工作。

But when you do this:但是当你这样做时:

revSTR( arr + 2, len );

You get get:你得到:

==7125== Command: ./program
==7125== 
ARR = A-
*** stack smashing detected ***: ./program terminated
==7125== 
==7125== Process terminating with default action of signal 6 (SIGABRT)
==7125==    at 0x4E6F428: raise (raise.c:54)
==7125==    by 0x4E71029: abort (abort.c:89)
==7125==    by 0x4EB17E9: __libc_message (libc_fatal.c:175)
==7125==    by 0x4F5311B: __fortify_fail (fortify_fail.c:37)
==7125==    by 0x4F530BF: __stack_chk_fail (stack_chk_fail.c:28)
==7125==    by 0x400637: main (program.c:14)

And this happens because in the first code, the length of arr is checked inside of revSTR() which is fine, but in the second code where you pass the length:发生这种情况是因为在第一个代码中,在revSTR()内部检查了arr的长度,这很好,但是在您传递长度的第二个代码中:

revSTR( arr + 2, len );

the Length is now longer then the actually length you pass when you say arr + 2 . Length 现在比你说arr + 2时通过的实际长度更长。

Length of strlen ( arr + 2 ) != strlen ( arr ) . strlen ( arr + 2 ) != strlen ( arr )长度。

Stack corruptions ususally caused by buffer overflows.堆栈损坏通常由缓冲区溢出引起。 You can defend against them by programming defensively.您可以通过防御性编程来防御它们。

Whenever you access an array, put an assert before it to ensure the access is not out of bounds.每当您访问一个数组时,在它之前放置一个断言以确保访问不会越界。 For example:例如:

assert(i + 1 < N);
assert(i < N);
a[i + 1] = a[i];

This makes you think about array bounds and also makes you think about adding tests to trigger them if possible.这让您考虑数组边界,也让您考虑在可能的情况下添加测试来触发它们。 If some of these asserts can fail during normal use turn them into a regular if .如果这些断言中的一些在正常使用期间可能失败,请将它们转换为常规if

我在使用 malloc() 为 struct * 分配一些内存时遇到了这个错误,在调试代码之后,我终于使用了 free() 函数来释放分配的内存,随后错误消息消失了:)

Another source of stack smashing is (incorrect) use of vfork() instead of fork() .堆栈粉碎的另一个来源是(不正确)使用vfork()而不是fork()

I just debugged a case of this, where the child process was unable to execve() the target executable and returned an error code rather than calling _exit() .我刚刚调试了一个案例,其中子进程无法execve()目标可执行文件并返回错误代码而不是调用_exit()

Because vfork() had spawned that child, it returned while actually still executing within the parent's process space, not only corrupting the parent's stack, but causing two disparate sets of diagnostics to be printed by "downstream" code.因为vfork()已经产生了那个孩子,它在实际上仍在父进程空间内执行时返回,不仅破坏了父进程的堆栈,而且导致“下游”代码打印两组不同的诊断信息。

Changing vfork() to fork() fixed both problems, as did changing the child's return statement to _exit() instead.vfork()更改为fork()解决了这两个问题,将 child 的return语句更改为_exit()

But since the child code precedes the execve() call with calls to other routines (to set the uid/gid, in this particular case), it technically does not meet the requirements for vfork() , so changing it to use fork() is correct here.但是由于子代码在execve()调用之前调用了其他例程(在这种特殊情况下设置 uid/gid),它在技术上不满足vfork()的要求,因此将其更改为使用fork()在这里是正确的。

(Note that the problematic return statement was not actually coded as such -- instead, a macro was invoked, and that macro decided whether to _exit() or return based on a global variable. So it wasn't immediately obvious that the child code was nonconforming for vfork() usage.) (请注意,有问题的return语句实际上并不是这样编码的——而是调用了一个宏,该宏决定是_exit()还是基于全局变量return 。因此,子代码并不是很明显不符合vfork()使用。)

For more information, see:有关更多信息,请参阅:

The difference between fork(), vfork(), exec() and clone() fork()、vfork()、exec()和clone()的区别

I am executing my a.out file.我正在执行我的a.out文件。 After execution the program runs for some time then exits with the message:执行后,程序将运行一段时间,然后退出并显示以下消息:

**** stack smashing detected ***: ./a.out terminated*
*======= Backtrace: =========*
*/lib/tls/i686/cmov/libc.so.6(__fortify_fail+0x48)Aborted*

What could be the possible reasons for this and how do I rectify it?可能是什么原因造成的,我该如何纠正?

I encountered this when I edited the struct, but didn't recompile libs that use that struct.我在编辑结构时遇到了这个问题,但没有重新编译使用该结构的库。 In some big project I added new fields to struct, that later are getting parsed from json in lib_struct, and this lib is later used in widgets to show what is parsed.在一些大项目中,我向结构中添加了新字段,这些字段后来从 lib_struct 中的 json 进行了解析,此库后来用于小部件以显示解析的内容。 My make file didn't have the dependencies covered, so the lib didn't recompile after editing the struct.我的 make 文件没有涵盖依赖项,因此在编辑结构后 lib 没有重新编译。 My solution was to recompile all things that use the struct.我的解决方案是重新编译所有使用该结构的东西。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM