用Valgrind检测PostgreSQL内存泄露

Valgrind简介

Valgrind是一个开源工具集合,其中最有名的是Memcheck可用来检测C,C++程序的内存泄露,判断程序运行是否会crash或者产生不可预知的结果。

Valgrind Memcheck工具的用法

以下内容参考自Valgrind的quick start manual
http://www.valgrind.org/docs/manual/quick-start.html

  1. 首先需要准备程序,注意程序编译时必须打开DEBUG,gcc -g参数。同时建议使用-O0编译,以免编译器优化代码后Valgrind无法给出实际的代码位置。
  2. 如果你的程序是这样运行的
    myprog arg1 arg2
    

    使用 valgrind 这样运行

    Valgrind --leak-check=yes myprog arg1 arg2
    The --leak-check option turns on the detailed memory leak detector
    
  3. 例子
    需要跟踪的程序代码
    这部分代码将有两处错误可以被检测到
    #include <stdlib.h>
    
    void f(void)
    {
     int x = malloc(10  sizeof(int));
     x[10] = 0;        // problem 1: heap block overrun
    }                        // problem 2: memory leak -- x not freed
    
    int main(void)
    {
     f();
     return 0;
    }
    

    跟踪到的结果及解释
    第一个错误 heap block overrun

    ==19182== Invalid write of size 4  # 错误类型,一次越界写产生的invalid write
    ==19182==    at 0x804838F: f (example.c:6)   # 下面是进程的stack trace
    ==19182==    by 0x80483AB: main (example.c:11)
    ==19182==  Address 0x1BA45050 is 0 bytes after a block of size 40 alloc'd    # 描述产生错误的内存地址
    ==19182==    at 0x1B8FF5CD: malloc (vg_replace_malloc.c:130)
    ==19182==    by 0x8048385: f (example.c:5)
    ==19182==    by 0x80483AB: main (example.c:11)
    19182表示PID
    

    第二个错误,内存泄露

    ==19182== 40 bytes in 1 blocks are definitely lost in loss record 1 of 1  # 错误类型,产生内存泄露
    ==19182==    at 0x1B8FF5CD: malloc (vg_replace_malloc.c:130)  # 请忽略该系统调用
    ==19182==    by 0x8048385: f (a.c:5)  # 这里是产生错误的根源
    ==19182==    by 0x80483AB: main (a.c:11)
    

    产生内存泄露的类型非常多,最常见的两种

    "definitely lost": your program is leaking memory -- fix it!  必须fix的
    "probably lost": your program is leaking memory, unless you're doing funny things with pointers (such as moving them to point to the middle of a heap block).   需要关注的,做一些操作时才会触发。
    

    如果报了一些未初始化值(uninitialised values)的错误,则需要给valgrind加--track-origins=yes参数,输出更详细的信息来分析。

如何检测PostgreSQL内存泄露

首先需要安装valgrind以及开发包

yum install -y valgrind valgrind-devel

PostgreSQL 9.4开始,内核层面支持valgrind。
编译前需要改一下头文件。

src/include/pg_config_manual.h

把#define USE_VALGRIND的注释去掉

/*
 * Include Valgrind "client requests", mostly in the memory allocator, so
 * Valgrind understands PostgreSQL memory contexts.  This permits detecting
 * memory errors that Valgrind would not detect on a vanilla build.  See also
 * src/tools/valgrind.supp.  "make installcheck" runs 20-30x longer under
 * Valgrind.  Note that USE_VALGRIND slowed older versions of Valgrind by an
 * additional order of magnitude; Valgrind 3.8.1 does not have this problem.
 * The client requests fall in hot code paths, so USE_VALGRIND also slows
 * native execution by a few percentage points.
 *
 * You should normally use MEMORY_CONTEXT_CHECKING with USE_VALGRIND;
 * instrumentation of repalloc() is inferior without it.
 */
#define USE_VALGRIND

/*
 * Define this to check memory allocation errors (scribbling on more
 * bytes than were allocated).  Right now, this gets defined
 * automatically if --enable-cassert or USE_VALGRIND.
 */
#if defined(USE_ASSERT_CHECKING) || defined(USE_VALGRIND)
#define MEMORY_CONTEXT_CHECKING
#endif

编译参数

CFLAGS=-O0 ./configure --prefix=/home/digoal/pgsql9.5 --enable-debug
gmake world -j 32
gmake install-world -j 32

确认编译正确

$ pg_config

得到如下结果

CFLAGS = -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -g -O0

启用Valgrind调试PostgreSQL

初始化数据库集群,配置数据库配置文件等,略。
使用 Valgrind启动数据库(需要指定PostgreSQL源码中的src/tools/valgrind.supp,这个文件是按照Valgrind提供的格式写的,有兴趣可以研究一下它的内容)

$ cd postgresql-9.5.3_src/

$ valgrind --leak-check=yes --gen-suppressions=all \
    --suppressions=src/tools/valgrind.supp --time-stamp=yes \
    --log-file=/tmp/%p.log --trace-children=yes \
    --track-origins=yes --read-var-info=yes \
    --show-leak-kinds=all -v \
    postgres --log_line_prefix="%m %p " \
    --log_statement=all --shared_buffers=4GB 2>&1 | tee /tmp/postmaster.log

启动会非常慢,等待它启动完成。

Valgrind的参数略
Valgrind --help

regresstest模式

另外开启一个会话

cd postgresql-9.5.3_src
make installcheck

观察 --log-file=/tmp/%p.log 日志

用户定制调试

另外开启一个会话
查询backend pid

select * from pg_backend_pid();

输入需要测试的SQL

观察pid对应的 --log-file=/tmp/%p.log 日志

小结

参考

时间: 2024-08-20 02:35:36

用Valgrind检测PostgreSQL内存泄露的相关文章

valgrind 检测 php-fpm 内存泄漏

最近线上服务器安装了一些扩展,导致 php-fpm 内存增长过快,虽然可以通过配置最大请求数和定时脚本来重启 php-fpm ,但是也抱着学习折腾的精神来学习下valgrind的使用. 下面的配置都是在我自己的服务器上测试,就是该博客运行的服务器上. 下载安装 wget http://valgrind.org/downloads/valgrind-3.12.0.tar.bz2 tar -jxvf valgrind-3.12.0.tar.bz2 cd valgrind-3.12.0 ./autog

linux中使用valgrind检测内存泄露

众所周知,c或者c++编写的程序很容易出现内存泄露问题.valgrind是一个很好的工具,可以检测程序中的内存泄露问题.什么是内存泄露 内存泄露可以分为两种: 一种是,程序中有指针指向通过malloc或者new申请的内存,但是在程序结束前,一直未收回.如果这种内存一直增加的话,可能导致内存耗尽.不过程序结束后系统会自动回收这些内存. 另一种是,通过malloc或者new申请的内存,但是程序中已经没有指针指向申请的内存.程序一直在执行,泄露的内存会越来越多,可能会耗尽程序的堆内存. 如何使用val

htmlcxx中css文件解析中yyparse有内存泄露,哪位大神能不能帮忙看一下

问题描述 htmlcxx中css文件解析中yyparse有内存泄露,哪位大神能不能帮忙看一下 使用最新版的htmlcxx0.85版,把内部的css解析部分抽出之后,检测出内存泄露

内存泄露-vc开发的程序占用内存一直在增大,是什么原因导致的?

问题描述 vc开发的程序占用内存一直在增大,是什么原因导致的? vc开发的程序占用内存一直在增大,是什么原因导致的?用bound checker也没检测到内存泄露啊,只是软件变得很卡. 解决方案 内存泄露只是没释放就直接放弃引用.也可能你一直引用着但是不再实际使用,这个是工具检查不出来的. 还是代码问题啊. 解决方案二: 你的程序有内存泄漏,多检查你的代码分配堆的地方 还有可能有其他资源泄漏.比如句柄,等 解决方案三: 1.你的程序应该是服务性程序吧,一直在运行: 2.检查自己检查代码,或者用内

Android 性能优化之使用MAT分析内存泄露问题

转载请注明本文出自xiaanming的博客(http://blog.csdn.net/xiaanming/article/details/42396507),请尊重他人的辛勤劳动成果,谢谢! 我们平常在开发Android应用程序的时候,稍有不慎就有可能产生OOM,虽然JAVA有垃圾回收机,但也不能杜绝内存泄露,内存溢出等问题,随着科技的进步,移动设备的内存也越来越大了,但由于Android设备的参差不齐,可能运行在这台设备好好的,运行在那台设备就报OOM,这些适配问题也是比较蛋疼的,比如我们平常

Visual C++内存泄露检测—VLD工具使用说明 .

Visual C++内存泄露检测-VLD工具使用说明 一.        VLD工具概述 Visual Leak Detector(VLD)是一款用于Visual C++的免费的内存泄露检测工具.他的特点有:可以得到内存泄漏点的调用堆栈,如果可以的话,还可以得到其所在文件及行号: 可以得到泄露内存的完整数据: 可以设置内存泄露报告的级别:并且是开源免费的.   二.        VLD下载 http://www.codeproject.com/tools/visualleakdetector.

C语言内存泄露检测--Memwatch

项目:迅雷下载库内存泄露检测 作者:曾金龙 供职:深圳迅雷网络技术股份有限公司 领域:迅雷下载库 时间:2014-07-26 迅雷的移动下载库是用C语言编写的,为了能够横跨欧亚非拉(ios,android,还有诺基亚的什么系统来着,对了symban)和性能,我们厂的下载库就选择了C,然后在C代码里面使用各种宏,预编译等来达到一 个下载库,多平台使用.不过平台相关的都已经约束在了一个叫common的库里面的一个子模块里面了.这极大的解放了我厂的码农朋友. 但是C毕竟是C,在聊起C的时候,我们组最喜

使用OptimizeIT进行Java内存泄露的检测

java程序也会引起内存泄露已经是公开的秘密了,工作中需要对该问题引起充分的重视. 市场上能够进行java内存检测的工具也有不少,我在工作中使用JBuilder自带的Optimize工具,现就最近一次使用Optimize的工程及经验进行以下梳理. 前一段时间根据需要,对工作中维护的某个模块进行了java内存泄露的测试,结果发现了很严重的问题:该模块一共有6大基本功能,每个功能每操作一次,大约要新消耗9-10k的内存空间,生成110个左右的新对象.作为商用软件产品是绝不允许这样的问题的出现的. O

Android内存泄露总结(附内存检测工具)

Java 中的内存分配 主要是分三块: 静态储存区:编译时就分配好,在程序整个运行期间都存在.它主要存放静态数据和常量. 栈区:当方法执行时,会在栈区内存中创建方法体内部的局部变量,方法结束后自动释放内存. 堆区:通常存放 new 出来的对象.由 Java 垃圾回收器回收. 栈与堆的区别 栈内存用来存放局部变量和函数参数等.它是先进后出的队列,进出一一对应,不产生碎片,运行效率稳定高.当超过变量的作用域后,该变量也就无效了,分配给它的内存空间也将被释放掉,该内存空间可以被重新使用. 堆内存用于存