A Tour of Windows CE Memory Tools

Posted by: Sue Loh

This list of tools completes what I started with my perf tool list from

Heap Memory Tools

Each of these tools works by hooking all of the heap allocation function calls.  The difference is mostly in how they’re controlled and how they collect their data.

Application Verifier

AppVerifier is Microsoft’s official tool for finding the source of a heap leak.  It shipped with the CE test kit (CETK) in 4.2 but in 5.0 it ships with the OS.  It records a callstack for each heap allocation, discarding data about allocations that are freed.  So in the end you can look to see which allocations were not freed, and get callstacks to identify them.  AppVerifier can be controlled over KITL from the desktop side, and it also has a device-side UI for controlling it on a standalone device.

In CE 4.2, AppVerifier was shipped as part of the Windows CE Test Kit (CETK), which I think you get as a separate install on top of Platform Builder.  In CE 5.0, AppVerifier is included with Platform Builder.  I’m actually unsure of whether you get it with Visual Studio or eVC, but I think you can.

AppVerifier is actually much more than a heap tool.  You can write an AppVerifier wrapper shim to catch any API call.  AppVerifier comes with a set of shim DLLs to wrap heap allocations, handle opens/closes and other interesting events.  But you could write your own shim to catch any API call and do something interesting with it.  The intention of AppVerifier is to catch programming mistakes in general, at run-time.  If you ever asked, “Who is calling API Foo()?” or wanted a log of API calls over time, AppVerifier is the tool for you.  You can’t ship an OS with shims in it, but you can use shims for all sorts of debugging scenarios.


CeLog Memtracking

I talk about CeLog a lot; it’s really just a logging engine.  But we’ve gone into the heap APIs and added CeLog logging calls to them, so you can set up CeLog to record a stream of heap calls.  It will also record callstacks for the heap accesses.  However we don’t ship any official tools to process that stream and do things like identify leaks.  There’s an unofficial tool — “memalyzer,” that you can use.  If you have Platform Builder you have memalyzer (it’ll be in your path if you open a build command window).  Memalyzer parses the CeLog log file and reports any leaks that it sees.

Also I should warn you that we might completely remove memalyzer in favor of AppVerifier.  After all, why maintain something that’s already replaced.  I’d rather have us spend the time to make AppVerifier better.


  • Since the memalyzer tool is unofficial, I don’t have any public documentation I can point you at.  🙁  It “just works,” right?!


LMEMDEBUG records all the heap operations (plus callstacks) into memory.  It discards callstacks for freed allocations, so that you only track callstacks for apparent leaks.  It can also give you heap statistics like total allocation counts and bucketed size histograms.  It is controlled entirely from the Target Control Window, so it requires KITL.  It comes with Platform Builder, and if you do a debug build it’ll be built and run by default.  On a retail build I think you have to build it manually (see public\common\oak\drivers\lmemdebug).


  • The only documentation I know about is in the OS tree, under %_WINCEROOT%\public\common\oak\drivers\lmemdebug\lmemdebug.txt.
    Again, I should warn you that we might completely remove lmemdebug in favor of AppVerifier.


Another company, Entrek, has a suite of tools that includes one which can catch heap leaks.  I think it is similar to AppVerifier.  It’s aimed at application developers instead of people who are using Platform Builder.



Despite the fact that they LOOK like they might be useful, I don’t find these tools good for investigating heap problems: Remote Performance Monitor, Remote Heap Walker, or the “hd” command in the Target Control Window.

Virtual Memory Tools

The Windows CE virtual memory model (32MB of VM per process) can lead to pain with virtual address space pressure.  Unfortunately our tools are not all that great, in my opinion.  🙁

The main thing these tools do underneath is call VirtualQuery on the entire range of address space.  So with some work you could write one yourself.

“mi” and friends

The Target Control Window (which requires KITL) has a “mi” command to get memory information.  If you run that command it’ll do a dump of VM usage per process.  There’s also a standalone version of this tool called “memtool” (it’s the same code, built into an EXE).  However I am pretty sure that writes to the debug output so it requires KITL too.


DevHealth (Windows Mobile 5 only)

If you have WM5, you should skip “mi” and use DevHealth.  It gets all the same information that “mi” does, plus a bunch more.  It adds up physical memory usage, and usage per heap.  DevHealth is an EXE which you can run on a standalone device, that outputs everything to a text file.  It comes with the Windows Mobile Platform Builder install, so if you’re an ISV you might have to finagle a copy from somewhere.


  • I’m sorry, I don’t know exactly where to send you but there is some documentation for DevHealth in the Windows Mobile docs.  Those aren’t online so I can’t give you a link to them.


Update, Feb. 15, 2006: Also see the dumpmem tool, http://support.microsoft.com/default.aspx?scid=kb;en-us;326164

Comments (13)

  1. Richard says:

    Hi Sue Loh,

    I find the memory allocating function is implemented in coredll.dll. My question is why not implement it in HAL?

    HAL layer function use the dll’s memory allocation function, so the memory allocated is not owned by the HAL process(nk.exe). It is dangous. It means the memory allocated for HAL can be paged out. If the memory allocated by the dll is paged out and cannot be paged in for some reason, the HAL will corrupt.

    I think WCE should have some reason why design like this and how to solve the problem I mentioned above.


  2. Richard says:

    Hi Sue Loh,

    Another question is reatively simple, see the following code in HAL(kernel):

    BOOL OEMIoControl(…)




    BOOL myIoCTL(void pInBuffer);


    //do something here…


    (struct A
    )pInBuffer->count = 1;

    //if pInBuffer is paged out here, interrupt

    //is disabled, it cannot be paged in //This may result system crash. Is that correct?


    //do some other thing here…


    If this is true, does that mean between interrupt diable and enable, we should not use passed in parameter?

  3. sloh says:

    Our heap implementation is in coredll.dll, but virtual and physical memory is all managed by the kernel. Heap memory is never paged, because Windows CE does not have a page file — there’s nowhere to page the memory to. So if you use the coredll routines to allocate memory, that memory won’t be paged out. In fact it is a rather odd thing in the first place, to use coredll to allocate memory from inside the OAL. I think the kernel might do it in a couple of places, but I’m not sure of that. Otherwise typically the kernel allocates memory using VirtualAlloc() (or an internal kernel equivalent) instead.


  4. sloh says:

    Hi Richard, if memory is paged out and interrupts are turned off, then there are two possible results I can think of. Maybe you’ll have interrupts turned off for a really long time while paging in. Or maybe the system will have an unrecoverable crash. I’m not sure which of the two you’d get; probably the crash. To avoid page faults while interrupts are turned off, you should call LockPages on the buffer before turning off interrupts. That will fault in any necessary pages, and prevent them from being paged out. Then call UnlockPages when you’re done with the buffer.


  5. B. Lee says:

    I really enjoyed your prior posts about using CeLog. It really helped out a lot. Can cook up something similar for profiling?

  6. Richard says:


    Thanks for your reply.

    I heard that memory page load process is a low level MMU interrupt and not disabled by normal disable interrupt. Is that correct?

  7. ce_base says:

    B. Lee: Yeah, I hope to do that. Stay tuned. I wish I was more consistent about posting things, but we are all busy folks.

    Richard: Hmm I don’t really know anything about that. The only comment I can provide is that I know some CPUs (ARM I think?) have a few different interrupt "priority" levels, and you can disable low-priority interrupts while still allowing high-priority interrupts to occur. Essentially allowing high-pri ISRs to interrupt low-pri ISRs. I don’t know which interrupts are high or low, and I’m not clear on which CPUs are like that.


  8. Richard says:


    Thanks anyway. I will update u if I haveany progrees on this.

  9. dramsier says:

    The "low level" interrupt referred to by Richard is typically an exception caused by an MMU abort, not an interrupt. Interrupts are one form of an exception, while MMU events are another. Disabling interrupts disables only the "interrupt" exception and has no effect on memory aborts.


  10. Frank says:

    What memory leak detection tools are available for Windows Mobile 5 for an application developer without Platform Builder? From my searches, AppVerifier does not support Windows Mobile 5 and neither do the tools from Entrek.


  11. ce_base says:

    Hi Frank, good question. You made me go ask the AppVerifier folks about that, and I got the lucky answer that AS OF TODAY you can now download AppVerifier for WM5 with no PB requirement. Check it out!


    Also, I suspect that Entrek’s tools work with WM5 already, but don’t know it for sure. I forwarded a link to your question to Entrek, asking them if they didn’t mind either answering me or posting a reply here directly. It was an "info" email address so I expect the response will be a little delayed. So check back here for more on that.


  12. Yes, Entrek Tools do work with VS 2005 and WM5. There are two caveats:

    1) Entrek tools use an older connectivity mechanism (Platform Manager) than what is available in VS 2005. VS 2005 uses Core Connectivity, a new technology introduced in VS 2005. To use Entrek tools, you still need Platform Manager. The best way to get that is to install eMbedded Visual C++ 4.0 from microsoft.com.

    2) Entrek ships a redistributable DLL from Microsoft (called dbghelp.dll) used for resolving addresses in your program to source code. That DLL is not compatible with VS 2005 symbols. So you have to rename or delete the file shipped by Entrek, and then set a path to the version installed by VS 2005 (or copy it to the Entrek directory).

    You’re now on your way!

    While I’m here, I should mention that we are releasing a major upgrade to our ProcMan tool. It includes support for directly connecting over ActiveSync, Platform Manager, and Core Connectivity. It is in beta now (send email to beta@entrek.com if you are interested in participating), and the beta does not support Core Connectivity, though the final bits will. However, the direct ActiveSync connectivity can be used with WM5.

    Give it a whirl. It will become a tool you use everyday.