建设建行积分兑换商城网站,宜城网站开发,wordpress按时间获取文章列表,中国商业网点建设开发中心官方网站1. 内存溢出
内存溢出 OOM #xff08;out of memory#xff09;#xff0c;是指程序在申请内存时#xff0c;没有足够的内存空间供其使用#xff0c;出现out of memory#xff1b;比如申请了一个int,但给它存了long才能存下的数#xff0c;那就是内存溢出。
2. 内存泄…1. 内存溢出
内存溢出 OOM out of memory是指程序在申请内存时没有足够的内存空间供其使用出现out of memory比如申请了一个int,但给它存了long才能存下的数那就是内存溢出。
2. 内存泄漏
内存泄露 memory leak是指程序在申请内存后无法释放已申请的内存空间一次内存泄露危害可以忽略但内存泄露堆积后果很严重无论多少内存,迟早会被占光。最终的结果就是导致OOM。
内存泄漏是指你向系统申请分配内存进行使用(new)可是使用完了以后却不归还(delete)结果你申请到的那块内存你自己也不能再访问也许你把它的地址给弄丢了而系统也不能再次将它分配给需要的程序。
3. 造成内存泄露常见的三种情况
1指针重新赋值
2错误的内存释放
3返回值的不正确处理
3.1 指针重新赋值
如下代码
char * p (char *)malloc(10);
char * np (char *)malloc(10);
其中指针变量 p 和 np 分别被分配了 10 个字节的内存。
如果程序需要执行如下赋值语句
pnp;
这时候指针变量 p 被 np 指针重新赋值其结果是 p 以前所指向的内存位置变成了孤立的内存。它无法释放因为没有指向该位置的引用从而导致 10 字节的内存泄漏。
因此在对指针赋值前一定确保内存位置不会变为孤立的。
类似的情况连续重复new的情况也是类似 int *p new int; p new int...;//错误
3.2 错误的内存释放
假设有一个指针变量 p它指向一个 10 字节的内存位置。该内存位置的第三个字节又指向某个动态分配的 10 字节的内存位置。
如果程序需要执行如下赋值语句时
free(p);
很显然如果通过调用 free 来释放指针 p则 np 指针也会因此而变得无效。np 以前所指向的内存位置也无法释放因为已经没有指向该位置的指针。换句话说np 所指向的内存位置变为孤立的从而导致内存泄漏。
因此每当释放结构化的元素而该元素又包含指向动态分配的内存位置的指针时应首先遍历子内存位置如本示例中的 np并从那里开始释放然后再遍历回父节点如下面的代码所示
free(p-np);
free(p);
3.3 返回值的不正确处理
有时候某些函数会返回对动态分配的内存的引用如下面的示例代码所示
char *f(){return (char *)malloc(10);
}
void f1(){f();
}
函数 f1 中对 f 函数的调用并未处理该内存位置的返回地址其结果将导致 f 函数所分配的 10 个字节的块丢失并导致内存泄漏。
4 在内存分配后忘记使用 free 进行释放
4. 如何避免内存泄露 确保没有在访问空指针。 每个内存分配函数都应该有一个 free 函数与之对应alloca 函数除外。 每次分配内存之后都应该及时进行初始化可以结合 memset 函数进行初始化calloc 函数除外。 每当向指针写入值时都要确保对可用字节数和所写入的字节数进行交叉核对。 在对指针赋值前一定要确保没有内存位置会变为孤立的。 每当释放结构化的元素而该元素又包含指向动态分配的内存位置的指针时都应先遍历子内存位置并从那里开始释放然后再遍历回父节点。 始终正确处理返回动态分配的内存引用的函数返回值。
5.定位内存泄漏valgrind重点
5.1、基本概念
Valgrind是一个GPL的软件用于LinuxFor x86, amd64 and ppc32程序的内存调试和代码剖析。你可以在它的环境中运行你的程序来监视内存的使用情况比如C 语言中的malloc和free或者 C中的new和 delete。使用Valgrind的工具包你可以自动的检测许多内存管理和线程的bug避免花费太多的时间在bug寻找上使得你的程序更加稳固。
安装Valgrind
//valgrind下载
http://valgrind.org/downloads/valgrind-3.12.0.tar.bz2valgrind安装
1. tar -jxvf valgrind-3.12.0.tar.bz2
2. cd valgrind-3.12.0
3. ./configure
4. make
5. sudo make install
应用环境Linux
编程语言C/C
使用方法 编译时加上-g选项如 gcc -g filename.c -o filename,使用如下命令检测内存使用情况
最常用的命令格式
valgrind --toolmemcheck --leak-checkfull ./testvalgrind --toolmemcheck --leak-checkfull --show-reachableyes --trace-childrenyes ./filename其中--leak-checkfull指的是完全检查内存泄漏--show-reachableyes是显示内存泄漏的地点--trace-childrenyes是跟入子进程。
如果您的程序是会正常退出的程序那么当程序退出的时候valgrind自然会输出内存泄漏的信息。如果您的程序是个守护进程那么也不要紧我们 只要在别的终端下杀死memcheck进程因为valgrind默认使用memcheck工具就是默认参数--toolsmemcheck
参数选择
-toolname 最常用的选项。运行 valgrind中名为toolname的工具。默认memcheck。memcheck ------ 这是valgrind应用最广泛的工具一个重量级的内存检查器能够发现开发中绝大多数内存错误使用情况比如使用未初始化的内存使用已经释放了的内存内存访问越界等。callgrind ------ 它主要用来检查程序中函数调用过程中出现的问题。cachegrind ------ 它主要用来检查程序中缓存使用出现的问题。helgrind ------ 它主要用来检查多线程程序中出现的竞争问题。massif ------ 它主要用来检查程序中堆栈使用中出现的问题。extension ------ 可以利用core提供的功能自己编写特定的内存调试工具-h –help 显示帮助信息。-version 显示valgrind内核的版本每个工具都有各自的版本。-q –quiet 安静地运行只打印错误信息。-v –verbose 更详细的信息, 增加错误数统计。-trace-childrenno|yes 跟踪子线程? [default: no]-track-fdsno|yes 跟踪打开的文件描述[default: no]-time-stampno|yes 增加时间戳到LOG信息? [default: no]-log-fdnumber 输出LOG到描述符文件 [2stderr]-log-filefile 将输出的信息写入到filename.PID的文件里PID是运行程序的进行ID-log-file-exactlyfile 输出LOG信息到 file-log-file-qualifierVAR 取得环境变量的值来做为输出信息的文件名。 [none]-log-socketipaddr:port 输出LOG到socket ipaddr:portLOG信息输出-xmlyes 将信息以xml格式输出只有memcheck可用-num-callersnumber show number callers in stack traces [12]-error-limitno|yes 如果太多错误则停止显示新错误? [yes]-error-exitcodenumber 如果发现错误则返回错误代码 [0disable]-db-attachno|yes 当出现错误valgrind会自动启动调试器gdb。[no]-db-commandcommand 启动调试器的命令行选项[gdb -nw %f %p]
设计思路根据软件的内存操作维护一个有效地址空间表和无效地址空间表进程的地址空间
相关推荐视频
实时线上内存泄漏检测的4种实现方式每一种都很重要
linux内存管理问题-如何理出自己的思路出来开发与面试双丰收
学习地址c/c linux服务器开发/后台架构师
需要C/C Linux服务器架构师学习资料加群812855908获取资料包括C/CLinuxgolang技术NginxZeroMQMySQLRedisfastdfsMongoDBZK流媒体CDNP2PK8SDockerTCP/IP协程DPDKffmpeg等免费分享 5.2、多个工具 1、Memcheck
最常用的工具用来检测程序中出现的内存问题所有对内存的读写都会被检测到一切对malloc()/free()/new/delete的调用都会被捕获。所以Memcheck 工具主要检查下面的程序错误
能够检测 使用未初始化的内存 (Use of uninitialised memory) 使用已经释放了的内存 (Reading/writing memory after it has been free’d) 使用超过 malloc分配的内存空间(Reading/writing off the end of malloc’d blocks) 对堆栈的非法访问 (Reading/writing inappropriate areas on the stack) 申请的空间是否有释放 (Memory leaks – where pointers to malloc’d blocks are lost forever) malloc/free/new/delete申请和释放内存的匹配(Mismatched use of malloc/new/new [] vs free/delete/delete []) src和dst的重叠(Overlapping src and dst pointers in memcpy() and related functions) 重复free Callgrind
和gprof类似的分析工具但它对程序的运行观察更是入微能给我们提供更多的信息。和gprof不同它不需要在编译源代码时附加特殊选项但加上调试选项是推荐的。Callgrind收集程序运行时的一些数据建立函数调用关系图还可以有选择地进行cache模拟。在运行结束时它会把分析数据写入一个文件。callgrind_annotate可以把这个文件的内容转化成可读的形式。
Cachegrind
Cache分析器它模拟CPU中的一级缓存I1Dl和二级缓存能够精确地指出程序中cache的丢失和命中。如果需要它还能够为我们提供cache丢失次数内存引用次数以及每行代码每个函数每个模块整个程序产生的指令数。这对优化程序有很大的帮助。
Helgrind
它主要用来检查多线程程序中出现的竞争问题。Helgrind寻找内存中被多个线程访问而又没有一贯加锁的区域这些区域往往是线程之间失去同步的地方而且会导致难以发掘的错误。Helgrind实现了名为“Eraser”的竞争检测算法并做了进一步改进减少了报告错误的次数。不过Helgrind仍然处于实验阶段。
Massif
堆栈分析器它能测量程序在堆栈中使用了多少内存告诉我们堆块堆管理块和栈的大小。Massif能帮助我们减少内存的使用在带有虚拟内存的现代系统中它还能够加速我们程序的运行减少程序停留在交换区中的几率。
5.3、使用原理 Memcheck 能够检测出内存问题关键在于其建立了两个全局表。
1、Valid-Value 表
对于进程的整个地址空间中的每一个字节(byte)都有与之对应的 8 个 bits对于 CPU 的每个寄存器也有一个与之对应的 bit 向量。这些 bits 负责记录该字节或者寄存器值是否具有有效的、已初始化的值。
2、Valid-Address 表
对于进程整个地址空间中的每一个字节(byte)还有与之对应的 1 个 bit负责记录该地址是否能够被读写。
检测原理 当要读写内存中某个字节时首先检查这个字节对应的 A bit。如果该A bit显示该位置是无效位置memcheck 则报告读写错误。 内核core类似于一个虚拟的 CPU 环境这样当内存中的某个字节被加载到真实的 CPU 中时该字节对应的 V bit也被加载到虚拟的 CPU 环境中。一旦寄存器中的值被用来产生内存地址或者该值能够影响程序输出则 memcheck 会检查对应的V bits如果该值尚未初始化则会报告使用未初始化内存错误。
5.4、具体使用
1. 使用未初始化的内存使用野指针
这里我们定义了一个指针p但并未给他开辟空间即他是一个野指针但我们却使用它了 Valgrind检测出我们程序使用了未初始化的变量但并未检测出内存泄漏。 2.在内存被释放后进行读/写使用野指针 p所指向的内存被释放了p变成了野指针但是我们却继续使用这片内存。 Valgrind检测出我们使用了已经free掉的内存并给出这片内存是哪里分配哪里释放的。 3.从已分配内存块的尾部进行读/写动态内存越界 我们动态地分配了一段数组但我们在访问个数组时发生了越界读写程序crash掉。 Valgrind检测出越界的位置。 注意Valgrind不检查静态分配数组的使用情况所以对静态分配的数组Valgrind表示无能为力比如下面的例子程序crash掉我们却不知道为什么。 4.内存泄漏 内存泄漏的原因在于没有成对地使用malloc/free和new/delete比如下面的例子。 Valgrind会给出程序中malloc和free的出现次数以判断是否发生内存泄漏比如对上面的程序运行memcheckValgrind的记录显示上面的程序用了1次malloc却调用了0次free明显发生了内存泄漏 上面提示了我们可以使用–leak-checkfull进一步获取内存泄漏的信息比如malloc和free的具体行号。 5. 不匹配地使用malloc/new/new[] 和 free/delete/delete[]
正常使用new/delete和malloc/free是这样子的 而不匹配地使用malloc/new/new[] 和 free/delete/delete[]则会被提示mismacth 6.两次释放内存
double free的情况同样是根据malloc/free的匹配对数来体现的比如free多了一次Valgrind也会提示。