精华内容
下载资源
问答
  • Windows 程序内存泄漏检测是一项十分重要的工作,基于 GUI 的应用程序通常在调试结束时也有内存泄漏报告,但这个报告的信息不全面,不能定位到产生泄漏的具体行号。其实自己实现一个内存泄漏检测工具是一件非常简单...


      Windows 程序内存泄漏检测是一项十分重要的工作,基于 GUI 的应用程序通常在调试结束时也有内存泄漏报告,但这个报告的信息不全面,不能定位到产生泄漏的具体行号。其实自己实现一个内存泄漏检测工具是一件非常简单的事情,但看过网上写的很多例子,普遍存在两种问题:

      1. 要么考虑不周全,一种环境下能用,而在另外一种环境下却不能很好工作,或者漏洞报告的输出方式不合理。
      2. 要么过于保守,例如:完全没有必要在 _malloc_dbg() 和 _free_dbg() 的调用前后用 CriticalSection 进行保护(跟踪一下多线程环境下 new 和 malloc 的代码就会明白)。

      内存检测主要用到以下几个 API,这些 API 能跟踪 new 和 malloc 系列方法申请的内存,具体说明参考帮助文档:

    复制代码
    struct _CrtMemState;
    
    _CrtSetDbgFlag();
    _CrtMemCheckpoint();
    _CrtMemCheckpoint();
    _CrtMemDifference();
    _CrtMemDumpStatistics();
    _malloc_dbg();
    _free_dbg();
    复制代码

     

    •   头文件:win32_crtdbg.h
    复制代码
    #pragma once
    
    #if defined _DEBUG && defined _DETECT_MEMORY_LEAK
    
    #ifdef new
        #undef new
    #endif
    
    #ifdef delete
        #undef delete
    #endif
    
    #ifndef _CRTDBG_MAP_ALLOC
        #define _CRTDBG_MAP_ALLOC
    #endif
    
    #include <crtdbg.h>
    
    namespace __dbg_impl
    {
        class CDebugEnv
        {
        public:
            CDebugEnv()
            {
                ::_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
                ::_CrtMemCheckpoint(&s1);
            }
    
            ~CDebugEnv()
            {
                ::_CrtMemCheckpoint(&s2);
    
                if (::_CrtMemDifference( &s3, &s1, &s2))
                {
                    TRACE0("!! Memory stats !!\n");
                    TRACE0("----------------------------------------\n");
                    ::_CrtMemDumpStatistics(&s3);
                    TRACE0("----------------------------------------\n");
                }
            }
    
        private:
            _CrtMemState s1, s2, s3;
        };
    
        static __dbg_impl::CDebugEnv __dbgEnv;
    }
    
    inline void* __cdecl operator new(size_t nSize, const char* lpszFileName, int nLine)
    {
        return ::_malloc_dbg(nSize, _NORMAL_BLOCK, lpszFileName, nLine);
    }
    
    inline void* __cdecl operator new[](size_t nSize, const char* lpszFileName, int nLine)
    {
        return operator new(nSize, lpszFileName, nLine);
    }
    
    inline void* __cdecl operator new(size_t nSize)
    {
        return operator new(nSize, __FILE__, __LINE__);
    }
    
    inline void* __cdecl operator new[](size_t nSize)
    {
        return operator new(nSize, __FILE__, __LINE__);
    }
    
    inline void* __cdecl operator new(size_t nSize, const std::nothrow_t&)
    {
        return operator new(nSize, __FILE__, __LINE__);
    }
    
    inline void* __cdecl operator new[](size_t nSize, const std::nothrow_t&)
    {
        return operator new(nSize, __FILE__, __LINE__);
    }
    
    inline void __cdecl operator delete(void* p)
    {
        ::_free_dbg(p, _NORMAL_BLOCK);
    }
    
    inline void __cdecl operator delete[](void* p)
    {
        operator delete(p);
    }
    
    inline void __cdecl operator delete(void* p, const char* lpszFileName, int nLine)
    {
        operator delete(p);
    }
    
    inline void __cdecl operator delete[](void* p, const char* lpszFileName, int nLine)
    {
        operator delete(p);
    }
    
    inline void __cdecl operator delete(void *p, const std::nothrow_t&)
    {
        operator delete(p);
    }
    
    inline void __cdecl operator delete[](void *p, const std::nothrow_t&)
    {
        operator delete(p);
    }
    
    #define new new(__FILE__, __LINE__)
    
    #endif // _DEBUG && defined _DETECT_MEMORY_LEAK
    复制代码

     

    •   实现文件:win32_crtdbg.cpp
    复制代码
    #include "stdafx.h"
    #include "win32_crtdbg.h"
    
    #if defined _DEBUG && defined _DETECT_MEMORY_LEAK
    
    __dbg_impl::CDebugEnv __dbgEnv;
    
    #endif // _DEBUG && defined _DETECT_MEMORY_LEAK
    复制代码

     

    • 使用方法
    1. 在 stdafx.h 或其他公共头文件中: #define_DETECT_MEMORY_LEAK#include"win32_crtdbg.h"
    2. 删除项目工程模板中自动生成的 new 操作符重定义,通常自动生成的 cpp 文件在 DEBUG 环境下会把 new 重定义为 DEBUG_NEW。
    • 存在问题

        对于某些全局变量指向的堆内存,如果 ~CDebugEnv() 被调用之时还没释放,则可能存在误报现象。这是一个老大难问题了,目前还没有完美的解决方法。

    展开全文
  • 小木发现线上的程序通过任务管理器发现内存不断的增长,怀疑是不是内存泄漏呢?用户态内存泄漏可能是句柄泄漏,堆内存泄露,Socket, GDI对象等等。而对于C++程序员来说,碰到最多的无疑是堆内存泄露:也就是通过...

    小木发现线上的程序通过任务管理器发现内存不断的增长,怀疑是不是内存泄漏呢?用户态内存泄漏可能是句柄泄漏堆内存泄露Socket, GDI对象等等。而对于C++程序员来说,碰到最多的无疑是堆内存泄露:也就是通过malloc或者new从堆上申请的内存,使用完成后,并没有释放,导致程序使用的内存越来越多。

    小木找到了一个分析利器UMDH: 这也是Windbg工具集中的其中一个利器,它可以在一个时间点记录程序的当前程序使用的堆内存申请的信息,过一段时间后再记录一次程序使用的堆内存申请的信息,然后比较两次的结果来找到这段时间内增加的堆内存及其关联的函数调用栈,从而查找内存泄露。为了分析问题,小木先尝试着写了以下测试程序, 熟悉下工具的使用。程序每隔十秒钟调用一次MemorLeakFunction ,在函数中每次会从堆上申请一段内存空间,并且没有释放。

    #include <iostream>
    #include <chrono>
    #include <thread>
    
    void MemoryLeakFunction()
    {
    	const int STR_SIZE = 100;
    	char * pStr = new char [STR_SIZE];
    	strcpy_s(pStr, STR_SIZE, "Memory Leak Sample");
    	std::cout << pStr << std::endl;
    }
    
    int main()
    {
    	while (true)
    	{
    		MemoryLeakFunction();
    		std::this_thread::sleep_for(std::chrono::seconds(10));
    	}
    	return 0;
    }
    

    第一步小木先使用gflag(这个也是Windbg工具集中的一个重要工具,主要用于修改系统的配置来达到调试的目的)。以下命令可以对MemoryLeak.exe程序申请堆上内存的时候记录其函数调用栈。
    "C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\gflags" -i MemoryLeak.exe +ust。直接运行gflags图形化界面打开如下图, 开启Create user mode stack trace database
    在这里插入图片描述

    第二步 运行测试程序MemoryLeak.exe

    第三步 将你程序的symbol文件MemoryLeak.pdb拷贝到mysymbols目录下。运行命令配置Symbol:Set _NT_SYMBOL_PATH=C:\mysymbols;SRV*C:\symbols*http://msdl.microsoft.com/download/symbols

    第四步 保存当前程序申请内存的记录,相当于做一个堆内存申请的Snapshot,并且将结果导入到C:\umdhlog\begin.log。运行命令(需要一些时间,请耐心等待哦)"C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\umdh" -pn:MemoryLeak.exe -f:C:\umdhlog\begin.log

    第五步 等程序运行一段时间后。这个等待的时间根据程序内存泄露的快慢来自行决定,要有足够的时间,来表现出程序使用堆上内存的差异。假设这里等待5分钟左右,再次运行如下命令,将结果导入到C:\undhlog\end.log中: "C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\umdh" -pn:MemoryLeak.exe -f:C:\umdhlog\end.log

    第六步 最后一步来比较end.logbegin.log内存申请的差异,来找到这段时间内增加的堆内存请求调用栈,并且导入到c:\umdhlog\diff.log。运行命令(有时候运行比较长,可以利用这段时间思考下人生吧):"C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\umdh" C:\umdhlog\begin.log C:\umdhlog\end.log -f:c:\umdhlog\diff.log

    最后一步 diff.log中可以看到增加的内存申请的函数调用栈,比如这段

    +    1194 (  157c -   3e8)     37 allocs	BackTrace1
    +      2d (    37 -     a)	BackTrace1	allocations
    
    	ntdll!RtlpAllocateHeap+2122
    	ntdll!RtlpAllocateHeapInternal+5E5
    	ucrtbase!_malloc_base+36
    	MemoryLeak!operator new+1F (d:\agent\_work\2\s\src\vctools\crt\vcstartup\src\heap\new_scalar.cpp, 35)
    	MemoryLeak!main+2D (c:\personal\git\beyourbest\cpp\windbgsample\memoryleak\memoryleaksample.cpp, 17)
    	MemoryLeak!__scrt_common_main_seh+10C (d:\agent\_work\2\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl, 288)
    	KERNEL32!BaseThreadInitThunk+14
    	ntdll!RtlUserThreadStart+21
    

    注意里面默认采用的是16进制表示的数量,比如0x1194表示在umdh比较的两个时间段之间,这段函数调用栈申请了4500个字节的堆空间,0x2d表示这之间调用了45次。 最关键的部分就是函数调用栈了,里面指明了在memoryleaksample.cpp文件的第17行进行了内存申请。这个时候我们一般对这段代码进行审查,都能够找出内存泄露的原因,比如这里的例子,使用后未释放内存。

    小木在熟悉了UMDH的使用后,对线上出现的实际问题进行分析,也很快找到了内存泄露原因。


    最后是个人微信公众号,文章CSDN和微信公众号都会发,欢迎一起讨论。
    在这里插入图片描述

    展开全文
  • 测试环境: E3-1231 v3 内存16G 程序内存的上限: 32位:1.97G 64位:7.60G 达到该峰值,程序运行将无法从堆中分配内存,会报异常。

    测试环境:

    E3-1231 v3 内存16G


    程序内存的上限:

    32位:1.97G

    64位:7.60G


    达到该峰值,程序运行将无法从堆中分配内存,会报异常。

    展开全文
  • Windows 32位程序内存扩展

    千次阅读 2017-12-28 10:15:41
    所有 32 位应用程序都有 4 GB 的进程地址空间(32 位地址最多可以映射 4 GB 的内存)。对于 Microsoft Windows 操作系统,应用程序可以访问 2 GB 的进程地址空间,称为用户模式虚拟地址空间。应用程序拥有的所有线程...

    所有 32 位应用程序都有 4 GB 的进程地址空间(32 位地址最多可以映射 4 GB 的内存)。对于 Microsoft Windows 操作系统,应用程序可以访问 2 GB 的进程地址空间,称为用户模式虚拟地址空间。应用程序拥有的所有线程都共享同一个用户模式虚拟地址空间。其余 2 GB 为操作系统保留(也称为内核模式地址空间)。所有操作系统版本(从 Windows 2000 Server 开始,包括 Windows Server 2003)都有一个 boot.ini 开关,可以为应用程序提供访问 3 GB 的进程地址空间的权限,从而将内核模式地址空间限定为 1 GB。

    访问进程地址空间的 AWE

    下一版本的 Microsoft SQL Server 将删除该功能。请不要在新的开发工作中使用该功能,并尽快修改当前还在使用该功能的应用程序。

    地址窗口化扩展插件 (AWE) 通过允许访问尽可能多的操作系统支持物理内存来扩展 32 位应用程序的功能。AWE 可以将最大内存容量 64 GB 的一部分映射到用户地址空间来实现此功能。应用程序缓冲池和 AWE 映射内存之间的映射通过操作 Windows 虚拟内存表来完成。

    为了支持 3 GB 的用户模式进程空间,必须将 /3gb 参数添加到 boot.ini 文件中并重新启动计算机,从而使 /3gb 参数生效。设置此参数后,用户应用程序线程可以寻址 3 GB 的进程地址空间,而为操作系统保留 1 GB 的进程地址空间。

    注意注意

    如果计算机上有 16 GB 以上的可用物理内存,操作系统需要 2 GB 的进程地址空间供系统使用,因此只能支持 2 GB 的用户模式地址空间。为了让 AWE 能够使用 16 GB 以上的内存,应确保 boot.ini 文件中没有/3gb 参数。否则,操作系统就不能寻址 16 GB 以上的内存。

    展开全文
  • private static System.Timers.Timer timer= new System.Timers.Timer(); private static int inTimer = 0; private static int time = 1; public Service1() ... timer.Elapsed += new System.Timers....
  • 尽管 Java™ 运行时能够解决大量的内存管理问题,但对程序内存占用情况保持警惕仍然是优化机器性能、测定内存泄露的关键。Windows 上有很多工具可以监控内存的使用。但每种工具各有长短,都有特定的倾向性,常常...
  • 监控Java应用程序Windows内存使用情况

    千次阅读 2019-01-20 17:08:42
    监控Java应用程序Windows内存使用情况
  • Windows 10 运行一段时间内存占用会爆满,Non-paged pool 占用内存会剧增,好多G。 网上查询资料,此情况通常是驱动之类导致的内存泄漏,尤其可能是网卡驱动。更新主板、网卡驱动之类后,发现并没有解决。进一步...
  • Unix内核态也称管态(Windows称内核模式)和用户态也称目态(Windows称用户模式)...而Unix稍显复杂,他把程序内存分为正文段和数据段,然后用一个PCB块(进程控制块)来指明各部分内存存放地址。正文段式程序是可再
  • vmmap是一个进程虚拟和物理内存分析实用程序。它显示进程提交的虚拟内存类型以及操作系统分配给这些类型的物理内存量(工作集)的细分。除了内存使用的图形化表示,vmmap还显示摘要信息和详细的进程内存映射。强大的...
  • 学习Windows程序设计也有一些时间了,为了记录自己的学习成果,以便以后查看,我希望自己能够坚持写下一系列的学习心得,对自己学习的内容进行总结,同时与大家交流。因为刚学习所以可能有的地方写不不正确,希望...
  • 修改游戏中的数据就是要找到并修改其所使用的内存所保存的内容,通常情况下由于进程之间的地址空间不能够互相访问,所以要想修改游戏中的数据必须借助API函数才能够使得自己的修改程序访问该游戏的内存。 一...
  • 如何降低Windows程序内存占用量

    千次阅读 2012-12-08 16:18:17
    *前记:这几天在优化系统的过程中,发现整个软件刚一开机就占了快200M的物理内存,在hp的工作站上面感觉都有点吃力,更别说在普通的PC上了。...在项目中对程序性能优化时,发现用SetProcessWorkingSetSize
  • windows内存中直接运行程序

    千次阅读 2018-12-26 16:33:19
    https://blog.csdn.net/zhang_ruiqiang/article/details/52262370
  • 内存是主要存储程序运行时所需要的机器代码,数据等内容。如何使用内存是每个程序员所必须要处理好的问题。本资源就为windows应用人员提供了很多关于内存管理操作的API函数以及如何使用它们。
  • 检测Windows程序中的内存使用错误

    千次阅读 2008-06-09 17:45:00
    检测Windows程序中的内存使用错误l 使用VC(VC2005/VC2008)编译程序时,如果你启动了“/RTC1”(VC6使用/GZ)去编译调试模式的程序,那么程序运行时VC的运行库就会使用特定的值填充申请和释放的内存,在调试内存错误...
  •  通常,我们的程序是保存在计算机的硬盘上的,程序的启动是通过操作系统将硬盘上的文件加载到内存中并进行执行的。然而,操作系统打开磁盘上的可执行文件后,该可执行文件就会处于被打开状态。这样会产生一个问题:...
  • windows 应用程序2g内存限制

    千次阅读 2013-02-25 16:49:41
    我也是网上听说的,32位系统最多能分配的内存是2^32 也就是差不多4G,然后去掉系统占用的一些乱七八糟的东西,最后分给用户能控制的地址段是2G 网上有这样一段话,仅供参考。 32位系统使用超过4GB的物理内存也...
  • 内存清理工具 Windows 内存程序是控制台应用程序,用C/C++写的。 使用EmptyWorkingSet/SetProcessWorkingSetSize实现内存清理与优化 程序只是对清理工具实现原理的一个展示,不建议大家使用来解决内存不够 详细...
  • Windows平台记录程序占用内存之二

    千次阅读 2018-06-07 17:04:58
    Windows平台中可以用Dos命令写批处理来记录某程序在使用过程中占用内存的情况,前提是要知道此程序的ID,批处理脚本内容如下: setlocal enabledelayedexpansion @echo off echo Input the PID set /p id=PID is:...
  • windows下在内存中运行程序

    千次阅读 2016-08-20 17:08:15
    程序加载到资源中,从资源加载到内存,并运行程序
  • 获取内存使用量 头文件#include&amp;lt;Psapi.h&amp;gt; HANDLE handle = GetCurrentProcess(); //获取当前进程句柄 PROCESS_MEMORY_COUNTERS pmc; GetProcessMemoryInfo(handle, &amp;amp;pmc, ...
  • 近几日分析的windows版本一个内存泄露故障,之前之后补了下功课,记录如下,分近10次才补充完整,可能不太连贯。
  • 本文讲述了应用程序在设备上运行时如何获取它运行时内存的详细状态。 简介 如果要测量你的应用程序是如何使用内存并对此作出修改,那么下面的代码将会给你帮助。从根本上说:DeviceStatus允许应用程序来获取设备的...
  • 每一个程序在执行时都占用一块可用的内存空间,用于存放动态分配的对象,此内存空间称为程序的自由存储区或堆。 C 语言程序使用一对标准库函数 malloc 和 free 在自由存储区中分配存储空间,而 C++ 语言则使用 ...
  • 1 获取内存使用量  获取内存使用量主要使用Psapi.h中声明的GetProcessMemoryInfo函数:  ①、在程序中添加#pragma comment(lib,”Psapi.lib”),将Psapi.lib包含进去,或者通过在工程的属性中添加Psapi.lib; ...
  • 页目录,页表2.Windows内存管理3.CPU段式内存管理4.CPU页式内存管理 一、基本概念1. 两个内存概念物理内存:人尽皆知,就是插在主板上的内存条。他是固定的,内存条的容量多大,物理内存就有多大(集成显卡系统除外...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 16,953
精华内容 6,781
关键字:

windows程序内存