c++程序内存问题

songweiwei_whu 2012-12-10 09:04:27
各位牛人,小弟最近遇到一麻烦,请大家帮帮忙。
我写了一个需要连续运行的程序(控制台的),运行时需要占用大概20M的内存,运行几天后,任务管理器内看该程序的内存占用没有太大变化,但是系统总的内存占用却不断增大直至系统崩溃,经过测试,大概一天能占用2~3G的内存。
我的程序是做科学计算的,每秒钟计算一次,计算过程几乎是一样的,但是内存的增长却不完全是逐步涨上去的。是涨一段 平一段 涨一段平一段,这个时间也没有周期性,可能是几个小时也可能是几分钟。
经过几天的排查发现一个更加奇怪的现象如果,如果将程序中的一处printf注释掉(该printf每秒输出一个约10000字节长度的字符串),那么程序内存涨的时间段短一些,平的时间段长一些,涨的时侯速度也没有变化,每天增加的内存降到原来的一半左右。

问了N多高手,都说是内存没释放。但个人觉得不是分配了内存没有被delte掉,理由如下:
1 我个人简单的测试了一下,如果 new了内存没有delete掉,那么任务管理器里面显示的该程序占用的内存会增大,但是我的程序在进程管理器里面看占用内存几乎不变。
2 同样是简单测试,如果new了内存没有被delete掉,那么当程序被关闭时内存会被系统回收,但我的程序在关掉后那几个G的内存却没有被回收,注销系统都不行,必须重新启动电脑才行。
仔细检查过程序,感觉真不太可能有这么大的内存泄漏,好像有一个黑洞在吃内存一样,排除电脑的问题(在两台服务器,一台电脑上都测试过)。
...全文
249 8 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
cocoabird 2012-12-12
  • 打赏
  • 举报
回复
能不能把代码贴上来
赵4老师 2012-12-12
  • 打赏
  • 举报
回复
检查是否资源泄漏的办法之一: 在任务管理器 进程 查看 选择列 里面选择:内存使用、虚拟内存大小、句柄数、线程数、USER对象、GDI对象 让你的程序(进程)不退出,循环执行主流程很多遍,越多越好,比如1000000次甚至无限循环,记录以上各数值,再隔至少一小时,越长越好,比如一个月,再记录以上各数值。如果以上两组数值的差较大或随时间流逝不断增加,则铁定有对应资源的资源泄漏!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef WIN32
    #include <windows.h>
    #include <io.h>
#else
    #include <unistd.h>
    #include <sys/time.h>
    #include <pthread.h>
    #define  CRITICAL_SECTION   pthread_mutex_t
    #define  _vsnprintf         vsnprintf
#endif
//Log{
#define MAXLOGSIZE 20000000
#define ARRSIZE(x) (sizeof(x)/sizeof(x[0]))
#include <time.h>
#include <sys/timeb.h>
#include <stdarg.h>
char logfilename1[]="MyLog1.log";
char logfilename2[]="MyLog2.log";
char logstr[16000];
char datestr[16];
char timestr[16];
char mss[4];
CRITICAL_SECTION cs_log;
FILE *flog;
#ifdef WIN32
void Lock(CRITICAL_SECTION *l) {
    EnterCriticalSection(l);
}
void Unlock(CRITICAL_SECTION *l) {
    LeaveCriticalSection(l);
}
#else
void Lock(CRITICAL_SECTION *l) {
    pthread_mutex_lock(l);
}
void Unlock(CRITICAL_SECTION *l) {
    pthread_mutex_unlock(l);
}
#endif
void LogV(const char *pszFmt,va_list argp) {
    struct tm *now;
    struct timeb tb;

    if (NULL==pszFmt||0==pszFmt[0]) return;
    if (-1==_vsnprintf(logstr,ARRSIZE(logstr),pszFmt,argp)) logstr[ARRSIZE(logstr)-1]=0;
    ftime(&tb);
    now=localtime(&tb.time);
    sprintf(datestr,"%04d-%02d-%02d",now->tm_year+1900,now->tm_mon+1,now->tm_mday);
    sprintf(timestr,"%02d:%02d:%02d",now->tm_hour     ,now->tm_min  ,now->tm_sec );
    sprintf(mss,"%03d",tb.millitm);
    printf("%s %s.%s %s",datestr,timestr,mss,logstr);
    flog=fopen(logfilename1,"a");
    if (NULL!=flog) {
        fprintf(flog,"%s %s.%s %s",datestr,timestr,mss,logstr);
        if (ftell(flog)>MAXLOGSIZE) {
            fclose(flog);
            if (rename(logfilename1,logfilename2)) {
                remove(logfilename2);
                rename(logfilename1,logfilename2);
            }
            flog=fopen(logfilename1,"a");
            if (NULL==flog) return;
        }
        fclose(flog);
    }
}
void Log(const char *pszFmt,...) {
    va_list argp;

    Lock(&cs_log);
    va_start(argp,pszFmt);
    LogV(pszFmt,argp);
    va_end(argp);
    Unlock(&cs_log);
}
//Log}
int main(int argc,char * argv[]) {
    int i;
#ifdef WIN32
    InitializeCriticalSection(&cs_log);
#else
    pthread_mutex_init(&cs_log,NULL);
#endif
    for (i=0;i<10000;i++) {
        Log("This is a Log %04d from FILE:%s LINE:%d\n",i, __FILE__, __LINE__);
    }
#ifdef WIN32
    DeleteCriticalSection(&cs_log);
#else
    pthread_mutex_destroy(&cs_log);
#endif
    return 0;
}
MSDN98中的例子walker又名pwalk。 完整列出指定进程的内存使用情况,显示进程地址空间内容,装载哪些DLL,代码、数据、堆栈段分配在何处,可以用来检测内存泄漏,监测内存使用。 http://download.csdn.net/detail/zhao4zhong1/3667896
songweiwei_whu 2012-12-11
  • 打赏
  • 举报
回复
补充一句,这个图是关闭了printf以后的测试结果
songweiwei_whu 2012-12-11
  • 打赏
  • 举报
回复
多谢1楼2楼的回复,我提出printf只是想把我所遇到的情况全部描述给大家,请大家帮忙,不过现在看感觉有点误导了。
个人觉得printf并没有问题,printf经过测试不管输出多少字符对程序都没有太大的影响,并且,程序中将所有输出(包括文件和printf)全部注释掉后,内存仍然会涨。
3楼的大侠,那个系统资源会是什么呢,有没有什么办法可以查(试过一些内存泄漏检查工具,没用)。
4楼的大侠,我的程序似乎只有一个进程(若干个线程),如果有进程没有关闭在哪里可以看得到呢 .
大家帮帮忙啊,小弟为这个东西都烦了半个月了,实在是没辙了哦,下面的图是内存占用图,我每秒记录了一次.
cocoabird 2012-12-10
  • 打赏
  • 举报
回复
widows下程序关闭资源会被回收的,除非还有程序相关的进程没关闭
prajna 2012-12-10
  • 打赏
  • 举报
回复
檢查一下程序中用到的系統資源吧,可能是系統資源沒有釋放。
stone2317 2012-12-10
  • 打赏
  • 举报
回复
这个主要是操作系统的问题,printf输出到显示屏上,在内存中会开辟一个缓冲区,显示屏在unix系统中是设备号1的,你printf的输出比较多,内存满了之后才会刷新缓冲区,再开辟新缓冲区位置所以内存一段平一段涨,
我爱小云 2012-12-10
  • 打赏
  • 举报
回复
应该是你控制台输出那里有问题,你想想,如果是输出了字符串,系统到底是放在哪里的,而且你不断输出,如果系统默认是程序运行时不回收这些资源,等程序结束了再统一回收会怎么样,输出缓冲区会越来越大 个人还是建议你输出到自己自定义的日志文件,而且以后要查看的时候也容易得多

3,882

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 其它技术问题
社区管理员
  • 其它技术问题社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧