GDIView is a unique tool that displays the list of GDI handles (brushes, pens, fonts, bitmaps, and others) opened by every process. It displays the total count for each type of GDI handle, as well as detailed information about each handle.
This tool can be useful for developers that need to trace GDI resources leak in their software.
In a previous article, the author devised a simple method to detect Graphical Device Interface (GDI) objects that are not properly released by Win32-based applications on Windows 9x platforms. Because some newer versions of Windows require a slightly different approach to GDI leaks, the author has updated his techniques for those operating systems. He builds and explains two tools designed to detect and eradicate GDI leaks in applications running on Windows XP, Windows 2000, and Windows NT.
This is example how to trace memory leaks using gflags and WinDbg.
I've some application called heaps1.exe which generates 1000000 (0xF4240) memory leaks elements of size 666 Bytes (0x29A).
1. Enable generating user mode stack trace database. You can also make it from GUI.
C:Program FilesDebugging Tools for Windows (x86)>gflags.exe /i heaps1.exe +ust
2. Run application and generate leaks.
3. Attach WinDbg to your process (heaps1.exe).
4. Load necessary symbols pdb.
5. Break into debugger if necessary.
6. And now magic words:
6a. At first check which heaps is leaking the most.
0:001> !heap -s
NtGlobalFlag enables following debugging aids for new heaps:
validate parameters
stack back traces
Heap Flags Reserv Commit Virt Free List UCR Virt Lock Fast
(k) (k) (k) (k) length blocks cont. heap
-----------------------------------------------------------------------------
00150000 58000062 1024 76 76 34 2 1 0 0 L
00250000 58001062 64 24 24 11 1 1 0 0 L
00260000 58008060 64 12 12 10 1 1 0 0 00390000 58001062 883776 679796 679796 6 1 1 0 0 L
003d0000 58001062 64 16 16 0 0 1 0 0 L
-----------------------------------------------------------------------------
OK. We see that heap 00390000 has outstanding amoutn of allocations.
6b. Let make statistics of this heap.
0:001> !heap -stat -h 00390000
heap @ 00390000
group-by: TOTSIZE max-display: 20
size #blocks total ( %) (percent of total busy bytes) 29a f4240 - 27b25a80 (99.99)
2012 2 - 4024 (0.00)
1504 1 - 1504 (0.00)
800 2 - 1000 (0.00)
204 3 - 60c (0.00)
214 2 - 428 (0.00)
400 1 - 400 (0.00)
5c 7 - 284 (0.00)
16 19 - 226 (0.00)
220 1 - 220 (0.00)
1fc 1 - 1fc (0.00)
7c 4 - 1f0 (0.00)
1c e - 188 (0.00)
34 6 - 138 (0.00)
98 2 - 130 (0.00)
28 7 - 118 (0.00)
88 2 - 110 (0.00)
80 2 - 100 (0.00)
fe 1 - fe (0.00)
2a 6 - fc (0.00)
OK. Now we see that almost all allocations have size 0x29a (666 Bytes) and there is 0xf4240 allocations of this size.
6c. Let check who allocated these bytes. There will come gigantic flood. You can break it by pressing <ctrl>+<break>
Fragmenting a heap is something I haven’t worried about for years. When you allocate and deallocate memory in certain patterns you can leave areas of unallocated memory stranded inamongst allocated memory. This can lead to the situation where you have, say, 10Mb of memory free, but yet an allocation for 256 bytes fails as although you have all this free memory, none if it is in a big enough continuous lump to give you your 256 bytes.
The LFH is not a separate heap. Instead, it is a policy that applications can enable for their heaps. When the LFH is enabled, the system allocates memory in certain predetermined sizes. When an application requests a memory allocation from a heap that has the LFH enabled, the system allocates the smallest block of memory that is large enough to contain the requested size. The system does not use the LFH for allocations larger than 16 KB, whether or not the LFH is enabled.
Applications that benefit most from the LFH are multi-threaded applications that allocate memory frequently and use a variety of allocation sizes under 16 KB. However, not all applications benefit from the LFH. To assess the effects of enabling the LFH in your application, use performance profiling data.
Under the classical model, when the request for 96 bytes comes in, the memory manager sees that 128-byte block (formerly known as p1) and splits it into two parts, a 96-byte block and a 32-byte block. The 96-byte block becomes block p3, and the 32-byte block sits around waiting for somebody to ask for 32 bytes (which never happens).
4. Low-fragmentation heap in Visual Studio 2010 and Windows Vista/7
Generally speaking, the low-fragmentation heap works pretty well for most classes of applications, and you should consider using it. (In fact, I'm told that the C runtime libraries have converted the default C runtime heap to be a low-fragmentation heap starting in Visual Studio 2010.)
Starting with Windows Vista, the system uses the low-fragmentation heap (LFH) as needed to service memory allocation requests. Applications do not need to enable the LFH for their heaps.
Why the low fragmentation heap (LFH) mechanism may be disabled on some computers that are running Windows Server 2003, Windows XP, or Windows 2000 http://support.microsoft.com/kb/929136
If you want to know the difference between System Committed memory and Process Committed memory, wondered what all those memory numbers shown by Task Manager really mean, or want to gain insight into the memory-related impact of a process, then this talk is for you. Using various memory analysis tools including: Process Explorer, VMMap, RAMMap, and others to highlight concepts throughout, the presentation starts with an overview of virtual memory management, describing types of process address space memory and how they impact system virtual memory. Then it dives into physical memory management, discussing how Windows manages process working sets, how it keeps track of physical memory, and how memory moves between different states.
Microsoft has implemented lots of useful functionality in Windows that they use in their own products. Many of these features can be used to enhance the security of third party applications, but not many developers or software architects know about them. This talk will detail some of the technical underpinnings of Windows features like UAC, IE protected mode and Terminal Serivces and show how they can be used to defend your own software from attack.
What This All Means
Overall, the results show that multithreaded file I/O can both improve or decrease performance significantly. Keep in mind that an application typically does not only read data, but also processes the data read in a more ore less CPU-intensive way. This leads to different results for every application and even tasks within a application. This also may or may not be the case for writing data. Furthermore, there are very different ways in how and when files will be read or written, as well as different hardware and software configurations that a application will meet. There is no general advice software developers can follow. For example, in one application I measured clearly that using multiple threads per sequential read file increased performance significantly in the 64-bit version. But with the 32-bit version more threads decreased performance on the same machine, the same operating system (Windows XP x64) and the same source code. In another case, where an application opened and appended thousands of files, the best solution was to create 8 threads that did nothing but close files (on a average dual-core machine).