内存检查工具Valgrind

官网介绍:http://www.valgrind.org/

Valgrind is an instrumentation framework for building dynamic analysis tools. There are Valgrind tools that can automatically detect many memory management and threading bugs, and profile your programs in detail. You can also use Valgrind to build new tools.

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 and branch-prediction profiler, and a heap profiler. It also includes three experimental tools: a stack/global array overrun detector, a second heap profiler that examines how heap blocks are used, and a SimPoint basic block vector generator. It runs on the following platforms: X86/Linux, AMD64/Linux, ARM/Linux, ARM64/Linux, PPC32/Linux, PPC64/Linux, PPC64BE/Linux, S390X/Linux, MIPS32/Linux, MIPS64/Linux, ARM/Android (2.3.x and later), X86/Android (4.0 and later), MIPS32/Android, X86/Darwin and AMD64/Darwin (Mac OS X 10.9, with limited support for 10.8).

Stack OverFlow 栈溢出 - stack smashing detected

在改造一个ota_ts_generator工具时,调试时,发生如下错误: 
        ./app 

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

Stack Smashing is actually a protection mechanism used by gcc to detect buffer overflow attacks. 

?
#include <stdio.h>
 
void func()
{
    char array[10];
    gets(array);
}
 
int main(int argc, char **argv)
{
    func();
}

【注释:】  An input of string greater than size 10 causes corruption of gcc inbuilt protection canary variable followed by SIGABRT to terminate the program.

    You can disable this protection of gcc using option -fno-stack-protector while compiling.
In that case you will get a segmentation fault if you try to access illegal memory location. and of course you can detect the point of overflow say for example using  valgrind.

另外一个例子:

#include <string.h>
   
void fn(void)
{
    char a[100];
    char *p = a;
    bzero(p, 1000);
}
   
int main(int argc, char *argv[])
{
     fn();
     return 0;
}

这里,数组a就会保存在栈中。当越界访问a[100]及后面的数据时,发生栈溢出,最容易出现的问题是返回指针被修改,进而函数返回时会发现返回的代码段指针错误,提示:“stack smashing detected...":

很多时候,当内存溢出问题不严重时,并不会直接终止我们程序的运行。但是,我们会在调试程序中碰到非常奇怪的问题,比如某一个变量无缘无故变成乱码,不管是在堆中,还是栈中。这便很有可能是指针的错误使用导致的。这种情况出现时,一种调试方法是:使用gdb加载程序,并用watch锁定被改成乱码的变量。这样,如果这个变量被修改,程序便会停下来,我们就可以看到底是哪条语句修改了这个程序。

总结:栈溢出,常常程序abort的地方并不是出问题的地方有,而是离产生问题的地方有一定距离,所以难以调试。

原文地址:https://www.cnblogs.com/youxin/p/4762786.html