valgrind --tool=memcheck --leak-check=full ./httptestios
valgrind --tool=memcheck --leak-check=full --track-origins=yes --show-reachable=yes ./httptestc++
用法: valgrind [options] prog-and-args [options]: 经常使用选项,适用于全部Valgrind工具编程
LOG信息输出数组
适用于Memcheck工具的相关选项:安全
// Automatic objects are not destroyed as a result of calling exit() #include <iostream> #include <chrono> #include <thread> #include <mutex> #include <pthread.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <error.h> #include <vector> #include <algorithm> #include <sstream> #include <string> int fail(const std::string str) { std::cerr<< str << std::endl; exit(1); } const std::string usage() { std::string a = "a"; return a; } int main() { fail(usage()); return 0; }
$ g++ -std=c++0x main.cpp -o xmain多线程
$ valgrind ./xmainsocket
==18699== definitely lost: 0 bytes in 0 blocks
==18699== indirectly lost: 0 bytes in 0 blocks
==18699== possibly lost: 26 bytes in 1 blocks
==18699== still reachable: 0 bytes in 0 blocks
==18699== suppressed: 0 bytes in 0 blocks
==18699== Rerun with --leak-check=full to see details of leaked memoryide
什么是coredump?函数
一般状况下coredmp包含了程序运行时的内存,寄存器状态,堆栈指针,内存管理信息等。能够理解为把程序工做的当前状态存储成一个文件。许多程序和操做系统出错时会自动生成一个core文件。工具
造成程序coredump的缘由不少,这里根据以往的经验总结一下:
1 内存访问越界
a) 因为使用错误的下标,致使数组访问越界
b) 搜索字符串时,依靠字符串结束符来判断字符串是否结束,可是字符串没有正常的使用结束符
c) 使用strcpy, strcat, sprintf, strcmp, strcasecmp等字符串操做函数,将目标字符串读/写爆。应该使用strncpy, strlcpy, strncat, strlcat, snprintf, strncmp, strncasecmp等函数防止读写越界。
2 多线程程序使用了线程不安全的函数。
应该使用下面这些可重入的函数,尤为注意红色标示出来的函数,它们很容易被用错:
asctime_r(3c) gethostbyname_r(3n) getservbyname_r(3n) ctermid_r(3s) gethostent_r(3n) getservbyport_r(3n) ctime_r(3c) getlogin_r(3c) getservent_r(3n) fgetgrent_r(3c) getnetbyaddr_r(3n) getspent_r(3c) fgetpwent_r(3c) getnetbyname_r(3n) getspnam_r(3c) fgetspent_r(3c) getnetent_r(3n) gmtime_r(3c) gamma_r(3m) getnetgrent_r(3n) lgamma_r(3m) getauclassent_r(3) getprotobyname_r(3n) localtime_r(3c) getauclassnam_r(3) etprotobynumber_r(3n) nis_sperror_r(3n) getauevent_r(3) getprotoent_r(3n) rand_r(3c) getauevnam_r(3) getpwent_r(3c) readdir_r(3c) getauevnum_r(3) getpwnam_r(3c)strtok_r(3c) getgrent_r(3c) getpwuid_r(3c) tmpnam_r(3s) getgrgid_r(3c) getrpcbyname_r(3n) ttyname_r(3c) getgrnam_r(3c) getrpcbynumber_r(3n) gethostbyaddr_r(3n) getrpcent_r(3n)
3 多线程读写的数据未加锁保护。
对于会被多个线程同时访问的全局数据,应该注意加锁保护,不然很容易形成core dump
4 非法指针
a) 使用空指针
b) 随意使用指针转换。一个指向一段内存的指针,除非肯定这段内存原先就分配为某种结构或类型,或者这种结构或类型的数组,不然不要将它转换为这种结构或类型 的指针,而应该将这段内存拷贝到一个这种结构或类型中,再访问这个结构或类型。这是由于若是这段内存的开始地址不是按照这种结构或类型对齐的,那么访问它 时就很容易由于bus error而core dump. 总线错误(bus error)一般是指针强制转换,致使CPU读取数据违反了必定的总线规则。《c专家编程》
#include <stdlib.h> #include <stdio.h> #if defined(__GNUC__) # if defined(__i386__) /* Enable Alignment Checking on x86 */ __asm__("pushf\norl $0x40000,(%esp)\npopf"); # elif defined(__x86_64__) /* Enable Alignment Checking on x86_64 */ __asm__("pushf\norl $0x40000,(%rsp)\npopf"); # endif #endif
int main() {
union{ char a[10]; int i; }u;
int *p =(int*)&(u.a[1]); *p =17; printf("%d\n", *p); } |
缘由是:
x86体系结构会把地址对齐以后,访问两次,而后把第一次的尾巴和第二次的头拼起来。
若是不是x86,那种体系结构下的机器不愿自动干这活,就会产生core。
若是在代码中将对齐检查功能打开,运行后能显示bus error。
5 堆栈溢出
不要使用大的局部变量(由于局部变量都分配在栈上),这样容易形成堆栈溢出,破坏系统的栈和堆结构,致使出现莫名其妙的错误。
在一般的编程开发与应用中,宽泛地讲,内存泄漏是分配了内存可是没有在程序终止前释放。严格且更有实际意义地讲,内存泄漏是分配了某块内存可是随后程序再也不拥有指向该内存的任何指针了。内存泄露检测工具valgrind使用的即是严格意义上内存泄露检测原则。下文若是没有特殊说明,一律指严格定义的内存泄露。内存泄露潜在地引发显著的堆消耗,特别对于长久持续运行的程序。关于“still reachable”类型的Valgrind内存泄露检测报告仅适用于宽泛定义的内存泄露。假如使用valgrind工具检测到了程序出现“still reachable”,说明程序没有释放这种类型的内存块,可是并不表明这些内存块永远的丢失了,不能被释放了,由于程序依然拥有指向这些内存块的指针。通常而言,它们不会引发严格意义上的内存泄露形成的问题(潜在的堆空间消耗以至无内存可用),因此不用担忧这些“still reachable”内存块。这是由于这些内存块一般申请一次,在进程的整个生命周期内一直保持着引用。固然,你也能够全程确保你的程序释放掉全部分配的内存。由于OS会在进程终止后回收进程的全部内存,所以这样作的意义不大。相反,若是存在真正的内存泄露,也许仅仅引发进程消耗的内存多于所需,也许程序运行时间足够长,引发一个进程耗尽内存。