Solaris 进程 heap段内存释放小研

作者: uNDeaD
Email: someonebw@gmail.com
Blog: http://blog.csdn.net/undead
转载请注明出处

 

最近观察生产平台上面的应用,发现应用进程所占用的内存是只增,不减,于是想深入看看,具体造成的原因。

 

   PID USERNAME  SIZE   RSS STATE  PRI NICE      TIME  CPU PROCESS/NLWP      
  5506 bwisp    1631M 1501M sleep   53    2  31:27:16 4.1% bwisp/275

标红的地方就是的

程序运行时间也就是5.12日开始的,到今天也没有几天,初始才300M;现在内存已经占用了1.6G

 

-bash-3.00$ pmap -x 5506|more
5506:   /sims/bwisp/bin/bwisp -d
         Address     Kbytes        RSS       Anon     Locked Mode   Mapped File
0000000100000000        512        480          -          - r-x--  bwisp
000000010017E000        112         24         24          - rwx--  bwisp
000000010019A000    1616168    1529064    1488736          - rwx--    [ heap ]//确实很大
FFFFFFFF4E600000         88         88          -          - r-x--  groupsend.so
FFFFFFFF4E714000         24         24         24          - rwx--  groupsend.so
FFFFFFFF4E800000         56         48          -          - r-x--  libgradequery.so
FFFFFFFF4E90C000         16         16         16          - rwx--  libgradequery.so
FFFFFFFF4EA00000         64         64          -          - r-x--  libsmsorder.so
FFFFFFFF4EB0E000          8          8          8          - rwx--  libsmsorder.so

 

确实是heap段,占用了大部分的内存。

按理说,进程new内存后,都会用free来进行释放,为什么heap段还是如此之大呢?问题产生了!

两种可能性

1。内存泄漏

2。操作系统本身的实现机制就是如此

 

通过实验来验证自己的想法!

实验用程序如下:


/*
 * main.cpp
 *
 *  Created on: 2010-4-9
 *      Author: Administrator
 */
 
//#include "SOTest.h"
 
#include <iostream>
 
#include <queue>
#include <string>
 
#include <dlfcn.h>
#include <link.h>
 
 
 
void *libSOTest = NULL;
 
void (*loadFun)(void) = NULL;
void (*unLoadFun)(void) = NULL;
void (*parseFun)(std::string &, std::string &, std::string &) = NULL;
 
bool LoadSO()
{
        if((libSOTest = dlopen("./libSOTest.so", RTLD_NOW | RTLD_GLOBAL)) != 0)
        {
                loadFun = (void (*)(void)) dlsym(libSOTest, "Load");
 
                if(dlerror())
                {
                        std::cout << "Load error :" << dlerror() << std::endl;
                }
 
                //
                unLoadFun = (void (*)(void)) dlsym(libSOTest, "Unload");
 
                if(dlerror())
                {
                        std::cout << "Unload error :" << dlerror() << std::endl;
                }
 
                //
                parseFun = (void (*)(std::string &, std::string &, std::string &)) dlsym(libSOTest, "Parse");
 
                if(dlerror())
                {
                        std::cout << "Parse error :" << dlerror() << std::endl;
                }
 
                return true;
        }
        else
        {
                std::cout << "LoadSO dlopen failed..." << std::endl;
 
                return false;
        }
}
 
void UnloadSO()
{
        if (libSOTest != NULL)
        {
                dlclose(libSOTest);
 
                libSOTest = NULL;
        }
}
 
 
 
int main(int argc, const char* argv[])
{
 
//      std::string v2 = "12345678";
//
//      std::string v = fun(v2);
//
//      std::cout << v << std::endl;
//
//      std::cout << "call que..." << std::endl;
//
//
//      CA que;
//
//
//
//      for(int i = 0; i < 10; i++)
//      {
//              char Data[64];
//
//              memset(Data,0,sizeof(Data));
//              sprintf(Data,"item_%02d = %d ",i, i);
//
//              std::cout << "call push()" << " " << Data << std::endl;
//
//              std::string v2 = Data;
//
//              que.push(v2);
//      }
//
//      std::cout << que.size() << std::endl;
//
//      v = "";
//
//      while(que.size() > 0)
//      {
//              que.pop(v);
//
//              std::cout << v << std::endl;
//      }
 
        while(true)
        {
                char in[256];
 
                memset(in,0,sizeof(in));
 
                gets(in);
 
                std::string in1 = in;
 
                std::cout << "in param:" << in1 << std::endl;
 
                if (in1 == "exit")
                {
                        break;
                }
 
                if (in1 == "new")
                {
                        void * pData[10000];
 
                        for(int i = 0; i < 10000; i++)
                        {
                                char *p = new char[10240];
 
                                if (p != NULL)
                                {
                                        p[10240 - 1] = 'a';
 
                                        pData[i] = p;
                                }
                                else
                                {
                                        std::cout << "new return null" << std::endl;
                                        break;
                                }
                        }
 
                        for(int j = 0; j < 10000; j++)
                        {
                                if (pData[j] != NULL)
                                {
                                        delete [] pData[j];
                                }
                        }
 
                        std::cout << "new end" << std::endl;
                }
 
                if (in1 == "load")
                {
                        LoadSO();
 
                        //
                        loadFun();
 
                        std::cout << "load end" << std::endl;
                }
 
                if (in1 == "unload")
                {
                        unLoadFun();
 
                        UnloadSO();
 
                        std::cout << "unload end" << std::endl;
                }
 
                if (in1 == "loadfile")
                {
                        std::string str1 = "loadfile";
                        std::string str2 = "./1.txt";
                        std::string str3 = "";
 
                        parseFun(str1, str2, str3);
 
                        std::cout << "loadfile end" << std::endl;
                }
 
                if (in1 == "info")
                {
                        std::string str1 = "info";
                        std::string str2 = "";
                        std::string str3 = "";
 
                        parseFun(str1, str2, str3);
 
                        std::cout << "info end return :" << str3 << std::endl;
                }
        }
 
 
 
        return 1;
}


-bash-3.00$ ./main3
load  //加载so
in param:load
CenterBuilder(): new Center()
libSOTest.so Load()
load end
loadfile    //加载1.txt文本
in param:loadfile
libSOTest.so  Parse() loadfile ./1.txt
loadfile end
unload //卸载so
in param:unload
libSOTest.so  Unload()
~CenterBuilder(): delete __pCenter
0 21643797 21643797 //后面两个数的差值,new的次数,free的次数
unload end

 


root@Bwisp-WT-01 # pmap -x 3547
3547:   ./main3
         Address     Kbytes        RSS       Anon     Locked Mode   Mapped File
0000000100000000         16         16          -          - r-x--  main3
0000000100102000          8          8          8          - rwx--  main3
0000000100104000       3056       2784       1544          - rwx--    [ heap ]
0000000100400000     249856     241664     241664          - rwx--    [ heap ] //so卸载后,free后,heap段内存依旧这么多
FFFFFFFF7DF00000          8          8          8          - rwx--    [ anon ]
FFFFFFFF7E200000         64         64         48          - rwx--    [ anon ]
FFFFFFFF7E300000          8          8          -          - r-x--  libc_psr.so.1
FFFFFFFF7E400000         40         16          -          - r-x--  libgcc_s.so.1
FFFFFFFF7E508000         16         16         16          - rwx--  libgcc_s.so.1
FFFFFFFF7E600000          8          8          8          - rwx--    [ anon ]
FFFFFFFF7E700000        944        824          -          - r-x--  libc.so.1
FFFFFFFF7E8EC000         64         64         56          - rwx--  libc.so.1
FFFFFFFF7E8FC000          8          8          8          - rwx--  libc.so.1
FFFFFFFF7EA00000        640        200          -          - r-x--  libm.so.2
FFFFFFFF7EB9E000         40         24          8          - rwx--  libm.so.2
FFFFFFFF7EC00000         64         48          -          - r-x--  libCrun.so.1
FFFFFFFF7ED0E000         16         16         16          - rwx--  libCrun.so.1
FFFFFFFF7ED12000         16          8          8          - rwx--  libCrun.so.1
FFFFFFFF7EE00000       1808        680          -          - r-x--  libCstd.so.1
FFFFFFFF7F0C2000         64         64         56          - rwx--  libCstd.so.1
FFFFFFFF7F0D2000          8          8          8          - rwx--  libCstd.so.1
FFFFFFFF7F100000          8          8          8          - rwx--    [ anon ]
FFFFFFFF7F200000        856        472          -          - r-x--  libstdc++.so.6
FFFFFFFF7F3D4000        248        144         48          - rwx--  libstdc++.so.6
FFFFFFFF7F500000         24         16         16          - rwx--    [ anon ]
FFFFFFFF7F600000        208        208          -          - r-x--  ld.so.1
FFFFFFFF7F734000         16         16         16          - rwx--  ld.so.1
FFFFFFFF7F738000          8          8          8          - rwx--  ld.so.1
FFFFFFFF7FFEA000         88         80         56          - rw---    [ stack ]
---------------- ---------- ---------- ---------- ----------
        total Kb     258208     247488     243608          -

 

 

通过pmap可以看到,so确实是卸载了,但是heap段没有释放

接下来可以通过gcore来看看,heap段的具体信息

 

gcore 3547 //生成进程的core

mdb core.3547

root@Bwisp-WT-01 # mdb core.3547
Loading modules: [ libc.so.1 ld.so.1 ]
> ::mappings
            BASE            LIMIT             SIZE NAME
       100000000        100004000             4000 a.out
       100102000        100104000             2000 a.out
       100104000        100400000           2fc000
       100400000        10f800000          f400000 [ heap ]
ffffffff7df00000 ffffffff7df02000             2000
ffffffff7e200000 ffffffff7e210000            10000
ffffffff7e300000 ffffffff7e302000             2000 /platform/sun4u-us3/lib/sparcv9/libc_psr.so.1
ffffffff7e400000 ffffffff7e40a000             a000 /usr/local/64/lib/libgcc_s.so.1
ffffffff7e508000 ffffffff7e50c000             4000 /usr/local/64/lib/libgcc_s.so.1
ffffffff7e600000 ffffffff7e602000             2000
ffffffff7e700000 ffffffff7e7ec000            ec000 /lib/sparcv9/libc.so.1
ffffffff7e8ec000 ffffffff7e8fc000            10000 /lib/sparcv9/libc.so.1
ffffffff7e8fc000 ffffffff7e8fe000             2000 /lib/sparcv9/libc.so.1
ffffffff7ea00000 ffffffff7eaa0000            a0000 /lib/sparcv9/libm.so.2
ffffffff7eb9e000 ffffffff7eba8000             a000 /lib/sparcv9/libm.so.2
ffffffff7ec00000 ffffffff7ec10000            10000 /usr/lib/sparcv9/libCrun.so.1
ffffffff7ed0e000 ffffffff7ed12000             4000 /usr/lib/sparcv9/libCrun.so.1
ffffffff7ed12000 ffffffff7ed16000             4000 /usr/lib/sparcv9/libCrun.so.1
ffffffff7ee00000 ffffffff7efc4000           1c4000 /usr/lib/sparcv9/libCstd.so.1
ffffffff7f0c2000 ffffffff7f0d2000            10000 /usr/lib/sparcv9/libCstd.so.1
ffffffff7f0d2000 ffffffff7f0d4000             2000 /usr/lib/sparcv9/libCstd.so.1
ffffffff7f100000 ffffffff7f102000             2000
ffffffff7f200000 ffffffff7f2d6000            d6000 /usr/local/64/lib/libstdc++.so.6
ffffffff7f3d4000 ffffffff7f412000            3e000 /usr/local/64/lib/libstdc++.so.6
ffffffff7f500000 ffffffff7f506000             6000
ffffffff7f600000 ffffffff7f634000            34000 /lib/sparcv9/ld.so.1
ffffffff7f734000 ffffffff7f738000             4000 /lib/sparcv9/ld.so.1
ffffffff7f738000 ffffffff7f73a000             2000 /lib/sparcv9/ld.so.1
ffffffff7ffea000 ffffffff80000000            16000 [ stack ]
>
> 100400000,f/apn                                                   //可以看到,数据还是在heap的内存中
0x100400000:    0x100400000:    0x3133343239383439
0x100400008:    0x3232370000000000
0x100400010:    0x3133343239383439
0x100400018:    0x3232390000000000
0x100400020:    0x3133343239383439
0x100400028:    0x3233300000000000
0x100400030:    0x3133343239383439
0x100400038:    0x3233390000000000
0x100400040:    0x3133343239383439
0x100400048:    0x3234310000000000
0x100400050:    0x3133343239383439
0x100400058:    0x3234320000000000
0x100400060:    0x3133343239383439
0x100400068:    0x3234350000000000
0x100400070:    0x3133343239383439
0x100400078:    0x3235330000000000
0x100400080:    0x3133343239383439
0x100400088:    0x3235350000000000
0x100400090:    0x3133343239383439
0x100400098:    0x3235380000000000
0x1004000a0:    0x3133343239383439
0x1004000a8:    0x3235390000000000
0x1004000b0:    0x3133343239383439
0x1004000b8:    0x3236300000000000
0x1004000c0:    0x3133343239383439
0x1004000c8:    0x3236380000000000
0x1004000d0:    0x3133343239383439
0x1004000d8:    0x3236390000000000
0x1004000e0:    0x3133343239383439
0x1004000e8:    0x3237300000000000
0x1004000f0:    0x3133343239383439
0x1004000f8:    0x3237360000000000
0x100400100:    0x3133343239383439
0x100400108:    0x3237370000000000
0x100400110:    0x3133343239383439
0x100400118:    0x3237380000000000
0x100400120:    0x3133343239383439
0x100400128:    0x3237390000000000
0x100400130:    0x3133343239383439
0x100400138:    0x3238320000000000

 

 

 

实验验证了我们的想法,并不是内存泄漏,new和free的次数是一致的,所以排除了这个可能!

证实了观点2,为操作系统的机制造成的!

 

如下:摘录自Solaris 内核结构

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值