How to Use Remote Tools to Track Memory Leaks in Windows CE Applications (Windows CE 5.0)

 

Mike Hall
Microsoft

January 2005

Applies to:
   Microsoft® Windows® CE 5.01

Summary: This article provides a hands-on overview about the debug tools which can be used to track leaks within a Windows CE based-application or driver. You will create, customize, build, download, debug, and use remote tools against a Windows CE 5.0 operating system image running on the Windows CE Emulator.
The lab will take approximately 60 minutes to complete. (39 printed pages)

Download Windows CE 5.0 Embedded Development Labs.msi from the Microsoft Download Center.

Contents

Part 1: Creating a Platform Image
Part 2: Customizing and Building the Platform
Part 3: Download the Platform
Part 4: Remote Tools and Memory Leaks
Part 5: Other Windows CE Remote Tools
Summary

Part 1: Creating a Platform Image

You will use the New Platform Wizard within Platform Builder to create an initial platform workspace that you will then modify by adding applications and updating the registry.

Start Platform Builder by clicking Start | AllPrograms | Windows CE 5.0 | Platform Builder. You are now ready to create a platform by using the Platform Wizard.

You can click the thumbnails for a larger image.

To create a new platform workspace

  1. Select File | New Platform.

    The dialog box in the following illustration outlines the process of creating a platform. Now you will step through the wizard and make selections as appropriate.

    Click here for larger image

    Click Next.

    As shown in the following illustration, the next step of the New Platform Wizard prompts you for the name and location of the platform you're going to build. In Microsoft® Windows® CE 4.2, the custom platforms would be created in the C:\WINCE420\PUBLIC folder. Windows CE 5.0, however, separates custom workspaces into a new folder named C:\WINCE500\PBWorkspaces.

    Click here for larger image

  2. Enter a name of MyPlatform.

  3. Click Next.

    You will build an operating system for the Windows CE 5.0 emulator by selecting EMULATOR:X86, as shown in the following illustration. If you wanted, you could select more than one reference board. Then, at build time, you could select which platform to build and download. Selecting both the emulator and a reference board may be useful when the hardware is still being developed because you can configure and test the operating system image in the emulator without needing physical hardware.

    Click here for larger image

  4. Click Next.

    You can now choose from a number of sample platforms, or if none of the options match your needs, you can simply select Custom Device and build the image based on the components you select from the catalog.

    For the purposes of this tutorial, you will select Internet Appliance from the list of platform configurations, as shown in the following illustration.

    Click here for larger image

  5. Click Next.

    While a number of options can be selected for each of the sample platforms, the Platform Wizard shows only options that are relevant to the platform you are building. For example, it would not make sense to include an Internet Explorer or WordPad application in a headless device, such as the Gateway. The Internet Appliance can include applications, such as the Internet browser, Microsoft Windows Media® Player, and Microsoft Windows Messenger, and can optionally include other applications. You can further customize your platform by including components from the catalog or by removing components from your project workspace.

    In this example, as shown in the following illustration, you don't need the Microsoft .NET Compact Framework or any of the Windows Media components, so you can clear these items.

    Click here for larger image

  6. Click Next.

    On the Networking and Communications page, you can see that Windows CE provides support for personal, local, and wide area networking. In this example, as shown in the following illustration, the default options are fine.

    Click here for larger image

  7. Click Next.

    As shown in the following illustration, the wizard is complete. You've configured the Windows CE platform, and you can now further customize the platform by adding or removing components from the platform.

    Click here for larger image

  8. Click Finish.

You now have a platform workspace containing all the Windows CE components that have been selected from the Platform Wizard. You could further customize the platform by adding additional technologies and platform specific drivers to your workspace, or you could remove any of the components that have been added by the wizard that are not needed by your platform.

Part 2: Customizing and Building the Platform

In this part of the exercise, you will perform the following procedures:

  • Enable the Profiling kernel and event tracking
  • Create and add the memLeak application to the platform
  • Create and add the GDILeak application to the platform
  • Create and add the Philosophers application to the platform
  • Configure the Philosophers application
  • Build the platform

The default build option is to generate a Release image of the operating system. As shown in the following illustration, use the toolbar to switch from Release build to Debug build.

Click here for larger image

You're now about ready to build the platform. But in the section, Part 4: Remote Tools and Memory Leaks, you will use the Remote Kernel Tracker tool; therefore, you need to enable the Profiling kernel.

To enable the Profiling kernel and event tracking

  1. Select Platform | Settings.

  2. Select the Build Options tab on the Platform Settings dialog box, as shown in the following illustration.

    Click here for larger image

    You will notice in the preceding illustration that the tools are currently set to build a Debug image of the platform. You have kernel debugging enabled, but to use the Remote Kernel Tracker tool, you also need to enable the Profiling kernel and event tracking.

  3. Select Enable Profiling.

  4. Select Enable Event Tracking During Boot.

  5. Click OK.

You have three applications to add to your platform: memLeak, GDILeak, and Philosophers. The source for these applications has already been written and is stored in the Code Clip application. You will now create and add these applications to the platform workspace.

The memLeak application is a Windows application with a user interface. You can use this application to show debug zones to display focused debug information from an application or driver, how Remote Performance Monitor can be used to monitor memory load within the operating system, and how CeLogData can be used to output custom data items into the Remote Kernel Tracker data stream. The memLeak application is multithreaded and is created using the Project Wizard. You will examine the code used in this application later in this lab.

To create and add the memLeak application to the platform

  1. Select File | New Project or File.

  2. Select WCE Application, as shown in the following illustration.

    Click here for larger image

  3. In the Project name box, type MemLeak.

  4. Click OK.

  5. Type your feature information as shown in the following illustration, and then click Next.

    Click here for larger image

    As the following illustration shows, you are presented with three options: An empty project, A simple Windows CE application, or a typical "Hello World" application.

    Click here for larger image

  6. Select A simple Windows CE application.

  7. Click Finish.

The Project Wizard has created a simple Win32 application, which has an entry point of WinMain and no additional code. You now need to add some code to this application.

  1. In the Workspace window, select File View.
  2. Expand the workspace to Projects | MemLeak | Source files.
  3. Double-click MemLeak.cpp. This step will open the source code to the memLeak application.
  4. Select all of the code for this application.
  5. Press DELETE to remove all of the code.
  6. Open Code Clip from the desktop.
  7. Locate and open the Platform Builder Advanced Lab item.
  8. Double-click MemLeak. This step copies the memLeak source to the Clipboard.
  9. In Platform Builder, select Edit | Paste, or right-click Paste. The memLeak code is added to the code window.

You're now ready to add your second application to the platform: GDILeak. This application is a Windows application with a user interface. The GDILeak application will be used to show how the Application Verifier tool can be used to examine the runtime of an application. When you write Win32 applications, it can be easy to overlook a graphics device interface (GDI) handle that was created to paint the client area of your application. Each GDI handle that is not released back to the operating system leaks 4 bytes. This amount can grow over time; therefore, you will run the Application Verifier tool to examine the runtime of this application.

To create and add the GDILeak application to the platform

  1. Select File | New Project or File.

  2. Select WCE Application as shown in the following illustration.

    Click here for larger image

  3. In the Project name box, type GDILeak.

  4. Click OK.

  5. Type your feature information, as shown in the following illustration, and then click Next.

    Click here for larger image

    As the following illustration shows, you are presented with three options: An empty project, A simple Windows CE application, or a typical "Hello World" application.

    Click here for larger image

  6. Select A simple Windows CE application.

  7. Click Finish.

The Project Wizard has created a simple Win32 application, which has an entry point of WinMain and no additional code. You now need to add some code to this application.

  1. In the Workspace window, select File View.
  2. Expand the workspace to C:\WINCE500 | Projects | GDILeak | Source files.
  3. Double-click GDILeak.cpp. This step opens the source code to the GDILeak application.
  4. Select all of the code for this application.
  5. Press DELETE to remove all of the code.
  6. Open Code Clip from the desktop.
  7. Locate and open the Platform Builder Advanced Lab item.
  8. Double-click GDILeak. This step copies the GDILeak source to the Clipboard.
  9. In Platform Builder, select Edit | Paste, or right-click Paste. The GDILeak source is added to the code window.

You're now ready to add your final application to the platform: Philosophers. This application is a Windows application with a user interface. In this example, you will be using the Dining Philosophers problem, which is a classic multiple-process synchronization problem. The problem consists of five philosophers sitting at a table who do nothing but think and eat. Between each philosopher, there is a single chopstick. In order to eat, a philosopher must have both chopsticks. A problem can arise if each philosopher grabs the chopstick on the right, and then waits for the chopstick on the left. In this case, a deadlock occurs, and all of the philosophers will starve. Also, the philosophers should be fair and not hold onto the chopsticks for too long; therefore, each philosopher should be able to eat as much as the others.

To create and add the Philosophers application to the platform

  1. Select File | New Project or File.

  2. Select WCE Application as shown in the following illustration.

    Click here for larger image

  3. In the Project name box, type Philo.

  4. Click OK.

  5. Type your feature information, as shown in the following illustration, and then click Next.

    Click here for larger image

    As the following illustration shows, you are presented with three options: An empty project, A simple Windows CE application, or a typical "Hello World" application.

    Click here for larger image

  6. Select A simple Windows CE application.

  7. Click Finish.

The Project Wizard has created a simple Win32 application, which has an entry point of WinMain and no additional code. You now need to add some code to this application.

  1. In the Workspace window, select File View.

  2. Expand the workspace to C:\WINCE500 | Projects | Philo | Source files.

  3. Double-click Philo.cpp. This step opens the source code to the Philo application.

  4. Select all of the code for this application.

  5. Press DELETE to remove all of the code.

  6. Open Code Clip from the desktop.

  7. Locate and open the Platform Builder Advanced Lab item.

  8. Double-click Philosophers. This step copies the Philosophers source to the Clipboard.

  9. In Platform Builder, select Edit | Paste, or right-click Paste. The Philosophers source is added to the code window.

    Now you're going to run the Remote Call Profiler against the Philosophers application. To do this, you need to make sure the Philo project is configured correctly.

To configure the Philosophers application

  1. In File view, right-click the Philo Project (the top node of the Philo application).

  2. Select Settings.

  3. Select and open Custom Variables, as shown in the following illustration.

    Click here for larger image

  4. Click New, as shown in the following illustration.

    Click here for larger image

  5. In the Variable name box, type WINCECALLCAP, as shown in the following illustration.

    Aa446911.windowsce_advanced21(en-us,MSDN.10).gif

  6. In the Variable value box, type 1.

  7. Click OK.

You also need to enable the generation of a .map file for this project.

  1. In the Custom Variables dialog box, click New.

  2. In the Variable name box, type WINCEMAP, as shown in the following illustration.

    Aa446911.windowsce_advanced22(en-us,MSDN.10).gif

  3. In the Variable value box, type 1.

  4. Click OK.

  5. Click OK.

You're now ready to build the platform.

To build the platform

  1. Select the OS Design View.
  2. Select Build OS | Sysgen.

**Note   **The build process will take approximately 10 minutes to complete.

Part 3: Download the Platform

In this part of the exercise, you will perform the following procedures:

  • Configure the debug and kernel transports
  • Download the operating system

Before you download the operating system image, check to make sure the debug and kernel transports are configured.

To configure the debug and kernel transports

  1. Select Target | ConnectivityOptions. The Target Device Connectivity Options dialog box opens, as shown in the following illustration.

    Click here for larger image

  2. In the Download and Transport boxes, select Emulator.

  3. Click Settings next to the Download box. The Emulator Download Settings dialog box opens, as shown in the following illustration.

    Click here for larger image

    You can set the download options for the Windows CE Emulator in this dialog box. The emulator runs as a fully functioning x86 CEPC reference board and includes support for networking, serial, and parallel devices by using your development computer's hardware devices.

  4. In the Memory box, select 64.

  5. Click OK.

  6. Click OK to close the Target Device Connectivity Options dialog box.

You are now ready to download the operating system.

To download the operating system

  • Select Target | Attach Device.

    The operating system image is downloaded to the emulator. After the operating system is downloaded, you will see a number of debug messages displayed in Platform Builder.

Part 4: Remote Tools and Memory Leaks

In this part of the exercise, you will perform the following procedures:

  • Use the Remote Performance Monitor tool to monitor the current memory load
  • Run the memLeak application to show leaks on the Remote Performance Monitor
  • View debug zone information in the memLeak application
  • Use the Remote Kernel Tracker tool to view the current memory load
  • Stop the memLeak application

The Remote Performance Monitor is a graphical tool for measuring the performance of a remote Windows CE system. You can view the behavior of performance objects, such as processors, memory, threads, and processes. Each performance object has an associated set of performance counters that provide information about device usage, queue lengths, and delays, and information used to measure throughput and internal congestion. Remote Performance Monitor provides the ability to track the current activity on a target device and the ability to view data from a log file.

You will use the Remote Performance Monitor to monitor the memory load on the reference board. This tool is useful to track memory load over a period of time; if memory load increases over time, this increase could be normal behavior of the currently running processes and drivers, or it could indicate a memory leak. You will use the memLeak application to show how the Remote Performance Monitor can be used.

To use the Remote Performance Monitor tool to monitor the current memory load

  1. In Platform Builder, select Tools | Remote Performance Monitor. You will be prompted for the device to connect to.

    Click here for larger image

  2. Expand Windows CE Default Platform, and then select Default Device.

  3. Click OK. After you connect to the device, you need to select which performance items you wish to monitor. In this procedure, you will be monitoring memory load.

  4. Select Edit | Add to Chart. The default objects displayed in the Add to Chart dialog box, which is shown in the following illustration, are power and battery status.

    Click here for larger image

  5. In the Object box, select CE Memory Statistics, as shown in the following illustration.

    Click here for larger image

  6. In the Counter box, select Memory Load.

  7. Click Add.

    Click Done. The Remote Performance Monitor will now display the current memory load, which should be a flat line. You can see from the following illustration that the operating system is running at about 17 percent memory load.

    Click here for larger image

You will now run the memLeak application that leaks memory and shows the leak on the Remote Performance Monitor.

To run the memLeak application to show leaks on the Remote Performance Monitor

  1. In Platform Builder, select Target | Run Program. The Run Program dialog box shows you all of the executable programs that are in the build directory for the MyPlatform workspace, as shown in the following illustration.

    Click here for larger image

  2. Select MemLeak.exe from the list of Available Programs.

  3. Click Run.

    In the Remote Performance Monitor, you will notice that the graph clearly shows a change in the memory load in the system, as shown in the following illustration. You can also obtain memory load information directly from your application by using the GlobalMemoryStatus application programming interface (API).

    Click here for larger image

    You're finished using the Performance Monitor so you can close this tool.

  4. Select File | Exit.

Now that your memLeak application is running, you can explore debug zones. Zones are useful in allowing a developer to dynamically alter the verbosity of debug message output to the kernel debugger. This alteration is helpful when you are trying to narrow in on the source of a problem.

Debug zones and the Windows CE Console Debug Shell tool (Cesh.exe) provide the ability to selectively turn the debugging message output from your code on and off by using macros. This allows you to trace execution of your code without halting the operating system. Tracing is a simple and non-intrusive way of catching problems in your code without causing the operating system to stop responding. Debug zones can be enabled either through Target Control or through the Platform Builder integrated development environment (IDE).

Debug zones are implemented by declaring a DBGPARAM structure in your source code. DBGPARAM is defined in dbgapi.h. DBGPARAM contains three elements. You can see these elements through the structure definition from dbgapi.h.

typedef struct _DBGPARAM {
  WCHAR    lpszName[32];     // @field Name of module
  WCHAR   rglpszZones[16][32]; // @field names of zones for first 16 
bits
  ULONG   ulZoneMask;          // @field Current zone Mask
} DBGPARAM, *LPDBGPARAM;

The following code example shows how the DBGPARAM structure is defined in the memleak application. In this example, you're only defining three zones: initialization, function tracing, and memory allocation/free. You can also see that initialization is enabled as the default zone. You could add tracing for any or all of the other zones.

DBGPARAM dpCurSettings = {
    TEXT("MemLeak"), {
        TEXT("Init"),TEXT("Trace Fn( );"),TEXT("Memory"),TEXT(""),
        TEXT(""),TEXT(""),TEXT(""),TEXT(""),
        TEXT(""),TEXT(""),TEXT(""),TEXT(""),
        TEXT(""),TEXT(""),TEXT(""),TEXT("")},
    // By default, turn on the zones for init and errors.
    ZONEMASK_INIT    
}; 

The memLeak application, like most of the operating system, is built to include debug zone information.

To view debug zone information in the memLeak application

  1. In Platform Builder, select Target, and then choose CE Debug Zones. The Debug Zones dialog box appears, as shown in the following illustration.

    Click here for larger image

  2. Click memLeak.exe in the Name list, and then note the zone information dynamically updates in the Debug Zones list.

    By way of demonstrating a zone, you'll enable Trace Fn() messages. This selection will enable debug output messages when the application allocates and releases memory.

  3. In the Debug Zones list, select Trace Fn( );, as shown in the following illustration.

    Click here for larger image

  4. Click OK.

    The following is the output from the memLeak application. You can see the flow of the application, AllocateMemory, UseMemory, and FreeMemory. You're tracing the entry point and exit points for these functions.

    --------------------------------------------
    4294949561 PID:2dda5912 TID:4dda5d36 0x8dd806dc: Enter - 
    AllocateMemory( ) Function
    4294949563 PID:2dda5912 TID:4dda5d36 0x8dd806dc: Leave - 
    AllocateMemory( ) Function
    4294949563 PID:2dda5912 TID:4dda5d36 0x8dd806dc: Enter - 
    UseMemory( ) Function
    4294949564 PID:2dda5912 TID:4dda5d36 0x8dd806dc: Leave - 
    UseMemory( ) Function
    4294949564 PID:2dda5912 TID:4dda5d36 0x8dd806dc: Enter - 
    FreeMemory( ) Function
    4294949564 PID:2dda5912 TID:4dda5d36 0x8dd806dc: Leave - 
    FreeMemory( ) Function
    4294950065 PID:2dda5912 TID:4dda5d36 0x8dd806dc: 
    --------------------------------------------
    

    This output simply shows the flow of the application, but it doesn't provide much additional debug information about memory allocation. You can enable the second debug zone to obtain more information from the application. Next, you'll enable memory tracing.

  5. In Platform Builder, select Target, and then choose CE Debug Zones. The Debug Zones dialog box appears.

  6. Click memLeak.exe in the Name list, and then note the zone information dynamically updates in the Debug Zones list.

  7. In the Debug Zones list, select Memory.

  8. Click OK.

    The following is the updated debug information from the memleak application. The highlighted areas show the additional debug information that has been added by enabling memory tracking.

    --------------------------------------------
     187306 PID:2dda5912 TID:4dda5d36 0x8dd806dc: Enter -
     AllocateMemory( ) Function
     187306 PID:2dda5912 TID:4dda5d36 0x8dd806dc: 
    Check GlobalMemoryStatus( )
     187306 PID:2dda5912 TID:4dda5d36 0x8dd806dc: Memory Load 24%
     187307 PID:2dda5912 TID:4dda5d36 0x8dd806dc: 
    Allocate TCHAR *2048 (4096 UNICODE Characters)
     187310 PID:2dda5912 TID:4dda5d36 0x8dd806dc: Pointer 0x310030
     187310 PID:2dda5912 TID:4dda5d36 0x8dd806dc: 
    Leave - AllocateMemory( ) Function
     187310 PID:2dda5912 TID:4dda5d36 0x8dd806dc: 
    Enter - UseMemory( ) Function
     187310 PID:2dda5912 TID:4dda5d36 0x8dd806dc: 
    Do Something Interesting here.
     187311 PID:2dda5912 TID:4dda5d36 0x8dd806dc: 
    Leave - UseMemory( ) Function
     187312 PID:2dda5912 TID:4dda5d36 0x8dd806dc: 
    Enter - FreeMemory( ) Function
     187312 PID:2dda5912 TID:4dda5d36 0x8dd806dc: Free Pointer 0x0
     187312 PID:2dda5912 TID:4dda5d36 0x8dd806dc: 
    Leave - FreeMemory( ) Function
     187814 PID:2dda5912 TID:4dda5d36 0x8dd806dc: 
    -------------------------------
    

    You can see that in the previous output, a pointer has been returned from the LocalAlloc function of 0x310030. You can also see that the FreeMemory function is calling is calling the LocalFree function and passing a pointer value of zero. You can assume that you're not using the same variable to allocate and free memory.

  9. Select ClassView for your platform workspace.

  10. Expand the memleak application. The expanded memleak application displays the various functions and variables contained within the memleak application, as shown in the following illustration. The AllocateMemory and FreeMemory functions are of particular interest.

    Click here for larger image

  11. On the ClassView tab, double-click the AllocateMemory function.

    In the following code sample, you're allocating 2048*sizeof(TCHAR). The result of calling LocalAlloc is being stored in a variable g_tcTemp.

    if (g_MemStatus.dwMemoryLoad < 60) {
    DEBUGMSG (ZONE_MEMORY, (TEXT("Allocate TCHAR *2048 
    (4096 UNICODE Characters)\n")));
        g_tcTemp=LocalAlloc(LPTR,(2048*sizeof(TCHAR)));
        DEBUGMSG (ZONE_MEMORY, (TEXT("Pointer 0x%lx\n"),g_tcTemp));
    } else {
    

    Now you can examine the FreeMemory function.

  12. On the ClassView tab, double-click the FreeMemory function.

    You can clearly see that you're using a variable called g_tc_Temp to free memory. This variable is initialized to NULL during the initialization of the application. The sample uses multiple variable names. In this example, the incorrect variable is being freed.

    void FreeMemory( )
    {
       DEBUGMSG (ZONE_TRACE, (TEXT("Enter - 
    FreeMemory( ) Function\n")));
       DEBUGMSG (ZONE_MEMORY, (TEXT("Free Pointer 0x%lx\n"),g_tc_Temp));
       LocalFree(g_tc_Temp);
       DEBUGMSG (ZONE_TRACE, (TEXT("Leave - 
    FreeMemory( ) Function\n")));
    }
    

By using the Remote Kernel Tracker tool, you can view thread interactions, internal dependencies, and system state information. The tool shows all processes and threads in the system; when processes and threads are created, ran, or stopped; when processes and threads are sleeping; system interrupts; and system events. These system events are mapped onto the thread that executed at the time they occurred.

The Remote Kernel Tracker tool is an essential tool for tracking real-time events (you will see how this works when you read the Real-Time article. But how can the Remote Kernel Tracker tool be used to track memory? The answer is simple, through the use of a call to the CeLogData API.

In the following code for the memleak application, you obtain the current memory load by calling GlobalMemoryStatus. You then call CeLogData by using the memory load as one of the parameters. In this example, you're outputting memory load whenever you allocate memory. You could output any useful information, including handles, events, threads, memory allocation, and free memory.

MEMORYSTATUS g_MemStatus;

memset(&g_MemStatus,0x00,sizeof(g_MemStatus));
g_MemStatus.dwLength=sizeof(g_MemStatus);
GlobalMemoryStatus(&g_MemStatus);
DEBUGMSG (ZONE_MEMORY, (TEXT("Memory Load 
%d%%\n"),g_MemStatus.dwMemoryLoad));

CeLogData(TRUE, CELID_RAW_LONG, &g_MemStatus.dwMemoryLoad, 
 (WORD) (sizeof(DWORD)), 1, CELZONE_MISC);

To use the Remote Kernel Tracker tool view the current memory load

  1. In Platform Builder, select Tools | Remote Kernel Tracker. You will be prompted for the device to connect to.

  2. Expand Windows CE Default Platform, and then select Default Device.

  3. Click OK.

    The Remote Kernel Tracker tool downloads a number of device side components to the emulator. After these components have been downloaded, the Remote Kernel Tracker tool displays all running processes and interruptions.

  4. In the Remote Kernel Tracker tool, expand Memleak.exe, as shown in the following illustration.

    You will notice two threads being displayed: one thread (identified as Memleak.exe) is the application thread and the second thread (identified as ?MemoryThread) is checking the memory load every 500ms. If the memory load is below 60 percent, ?MemoryThread allocates 2048*TCHAR.

    Click here for larger image

    So how do you locate our custom CeLogData information? The Remote Kernel Tracker tool can display vast amounts of information.

  5. Right-click MemoryThread, as shown in the following illustration.

    Click here for larger image

  6. Select Find Next Event on Thread.

    The Remote Kernel Tracker tool will "jump" to the next event on the selected thread. You will notice in the following illustration that a white square with four dots appears. This graphic is a custom (or CeLogData) item.

    Aa446911.windowsce_advanced36(en-us,MSDN.10).gif

  7. Move the pointer over the white square to view the "data tip." The information your code outputs is displayed.

    You will notice that the data tip shown in the following illustration has [Event Info] Raw long, 14 — This data tip shows that memory load was at 14 percent at the time you called CeLogData. (This value may be different on your system).

    Aa446911.windowsce_advanced37(en-us,MSDN.10).gif

  8. Close the Remote Kernel Tracker tool. If you're prompted to save data from Remote Kernel Tracker tool, select No.

  9. Close the Remote Performance Monitor tool. If you're prompted to save data, select No.

You also need to stop the memLeak application, which you can do in two ways: either through the Windows CE Target Control window or through the Platform Builder user interface directly.

To stop the memLeak application

  1. In Platform Builder, select Target | CE Processes.

  2. Select Memleak, as shown in the following illustration.

    Click here for larger image

  3. Click the red Close Process button.

  4. Click YES to close the process.

Part 5: Other Windows CE Remote Tools

There are a number of tools that ship with Windows CE that can be used to examine the operating system your embedded device is using. You will examine the use of the Application Verifier tool, the Remote Call Profiler tool, and the Monte Carlo Profiler tool.

Application Verifier Tool

In this part of the exercise, you will perform the following procedures:

  • Start the Application Verifier tool
  • Examine the GDILeak.exe application's output from the Application Verifier tool

The Application Verifier tool assesses the stability of an application and detects common programming mistakes. The tool attaches to an application and performs tests while the application runs. With the tool, you may be able to diagnose subtle problems with an application that would otherwise be difficult to diagnose on Microsoft Windows CE.

Each test that the Application Verifier tool runs is referred to as a shim. The tool inserts the shim into the code path between the calling function and the intended target function.

For a given application, you can select the shims that the Application Verifier tool uses to test the application. Examples of shims for the tool include tests for memory leaks, tests for the usage of specific APIs, and tests for memory corruption.

In this example, you will run a simple Win32 application that displays a bitmap in the client area of the applications window. To enable this functionality, you will load a bitmap from the applications resources by using LoadBitmap, obtain the dimensions of the bitmap using GetObject, select the bitmap into a temporary device context (created by using CreateCompatibleDC), and then copies the bitmap onto the primary Device Context by using BitBlt.

This process sounds simple, but there are a few errors that Win32 developers tend to make, for example, creating a temporary device context without cleaning up the resources when they're finished.

The following is the code for the drawing routine.

void DrawLogo(PAINTSTRUCT *ps)
{
    HBITMAP hBmp=SHLoadDIBitmap(L"\\Windows\\Windowsce.bmp");
    BITMAP bmp;

    GetObject(hBmp,sizeof(bmp),&bmp);

    HDC hDCTemp=CreateCompatibleDC(ps->hdc);
    HBITMAP hBmpOld=(HBITMAP)SelectObject(hDCTemp,hBmp);
    int iXPos=(ps->rcPaint.right-bmp.bmWidth)/2;
    int iYPos=(ps->rcPaint.bottom-bmp.bmHeight)/2;

    BitBlt(ps-
>hdc,iXPos,iYPos,bmp.bmWidth,bmp.bmHeight,hDCTemp,0,0,SRCCOPY);

}

You can start the Application Verifier tool from the Windows CE Test Kit. In the following procedure, you'll start the Application Verifier tool and run it against the ICOP x86 reference board.

To start the Application Verifier tool

  1. In Platform Builder, select Tools | Application Verifier. The Windows CE Application Verifier dialog box states that tool is not connected to the targeted device, as shown in the following illustration.

    Click here for larger image

    The Application Verifier tool uses a set of shim DLLs to intercept API calls. Windows CE ships with three shim DLLs, and these shim DLLs are used to track the handles SHELL and HEAP.

    In your sample application (GDILeak.exe), you allocate resources and then don't hand these resources back to the operating system. Each handle leaks 4 bytes. This amount may not sound substantial, but over the lifetime of an embedded system where applications run for days, months, or even years without being shutdown, the 4-byte leak can add up to megabytes of memory.

  2. Click Connect. The Device Connection dialog box prompts to select how to connect to the target device, as shown in the following illustration.

    Click here for larger image

  3. Clear the Use Windows Sockets for the client/server communication check box

  4. Under Platform Manager, click Connect. You will be prompted for the device to connect to.

  5. Select Windows CE Default Device.

  6. Click OK.

Now you can run the application and examine the output from the Application Verifier tool. You need to start the application from the Application Verifier tool. In this example, you are going to track user and GDI objects.

To examine the GDILeak.exe application's output from the Application Verifier tool

  1. In the Application Verifier tool, select Shell Verifier, as shown in the following illustration.

    Click here for larger image

  2. Click Add to add the test setting to the test.

  3. Expand the Windows folder, and then select GdiLeak.exe.

  4. Click Open.

  5. Click Run. The following illustration shows how the application looks on your x86 reference board. You can clearly see the Windows CE .NET bitmap being loaded from the application resource and being displayed on the client area of the application.

    Click here for larger image

  6. Close the application.

    Next, you can view the results in the Application Verifier tool.

  7. In the Application Verifier tool, click Get Logs.

  8. In the Application Verifier tool, click View Exported Log. In the following figure, you can see a leak in calls to LoadBitmap and CreateCompatibleDC.

**Note   **You should be calling DeleteDC and DeleteObject to clean up after you've finished using the objects.

Click here for larger image

This procedure is one example of how you can use the Application Verifier tool to track leaks in an application. In this example, you used GDI objects. You could also run additional tests on this application to verify the use of handles (file, registry) and heap.

Remote Call Profiler Tool

In this part of the exercise, you will perform the following procedure:

  • Open the Philosophers application with the Remote Call Profiler tool

The Remote Call Profiler tool combines profiling and analysis tools with a graphical interface that enables you to identify algorithmic bottlenecks in your code.

The technology in the Remote Call Profiler tool provides a graphical environment to display the information that you want to analyze. You can compare information from different sections of your data and view your data in a variety of formats.

In this example, you will use the Remote Call Profiler tool to determine where the time is being spent in the Philosophers application.

To open the Philosophers application with the Remote Call Profiler tool

  1. In Platform Builder, select Tools | Remote Call Profiler.

  2. Connect to Windows CE .NET Default Device.

  3. Select Launch.

  4. In the Launch dialog box, type the application name Philo.exe, as shown in the following illustration.

    Aa446911.windowsce_advanced44(en-us,MSDN.10).gif

    The Philosopher application will run without displaying any user interface. The application does output data to the debug window within Platform Builder. The following is an example of the output.

    3722641 PID:e3c55f36 TID:23a08d72 
    #0 waiting forever on right chopstick 23a0889a
    3722643 PID:e3c55f36 TID:23a08d72 
    #0 waiting forever on left chopstick 23a088fa
    3722652 PID:e3c55f36 TID:239e2802 #1 Eating
    3722653 PID:e3c55f36 TID:239e2802 
    #1 waiting forever on right chopstick 23a088fa
    3722681 PID:e3c55f36 TID:239e2fa6 #2 Eating
    3722682 PID:e3c55f36 TID:239e2fa6 
    #2 waiting forever on right chopstick 23a0895a
    3722683 PID:e3c55f36 TID:239e2fa6 
    #2 waiting forever on left chopstick 23a08a62
    3722691 PID:e3c55f36 TID:239e2f66 #3 Eating
    3722692 PID:e3c55f36 TID:239e2f66 
    #3 waiting forever on right chopstick 23a08a62
    3722706 PID:e3c55f36 TID:239de1aa #4 Eating
    3722707 PID:e3c55f36 TID:239de1aa 
    #4 waiting forever on right chopstick 23a08af2
    3722708 PID:e3c55f36 TID:239de1aa 
    #4 waiting forever on left chopstick 23a0889a
    3723145 PID:e3c55f36 TID:23a08d72 #0 PonderNothingness
    3723146 PID:e3c55f36 TID:239e2802 
    #1 waiting forever on left chopstick 23a0895a
    3723185 PID:e3c55f36 TID:239e2fa6 #2 PonderNothingness
    3723186 PID:e3c55f36 TID:239e2f66 
    #3 waiting forever on left chopstick 23a08af2
    3723649 PID:e3c55f36 TID:239de1aa #4 PonderNothingness
    3723688 PID:e3c55f36 TID:239e2802 #1 PonderNothingness
    3724147 PID:e3c55f36 TID:23a08d72 #0 Eating
    3724148 PID:e3c55f36 TID:23a08d72 
    #0 waiting forever on right chopstick 23a0889a
    3724149 PID:e3c55f36 TID:23a08d72 
    #0 waiting forever on left chopstick 23a088fa
    3724151 PID:e3c55f36 TID:239e2f66 #3 PonderNothingness
    3724187 PID:e3c55f36 TID:239e2fa6 #2 Eating
    

    The Remote Call Profiler tool provides a number of views of the data. The following illustration shows the TopX view. This view lists all of the functions called in the application, the number of times each function was called, and the amount of time spent in each function. You can see that the majority of time is spent in the function MySleep. If you examine the code for MySleep, you will see that this function calls Sleep(dwMilliseconds).

    Click here for larger image

    To use the Remote Call Profiler tool, an application must include cecap.h, must be compiled with the /Gh flag (or /callcap if not building for x86), and must be linked with cecap.lib. The x86 lib file is here - C:\Program Files\Common Files\Microsoft Shared\Windows CE Tools\Platman\sdk\wce420\platman\lib\target\x86.

Monte Carlo Profiler Tool

The Monte Carlo Profiler tool is a statistical software diagnostic tool in which the operating system is interrupted at a high rate and the interrupted address is recorded. From this information, the number of hits per routine is derived. This type of profiling does not measure or record execution time.

Monte Carlo profiling provides two approaches. The first, called process profiling, periodically tracks the current running routine. This is Monte Carlo profiling in the strict sense. A second profiling technique, called object call profiling, is akin to Monte Carlo profiling.

Monte Carlo profiling relies on the Windows CE profile-enabled kernel (you enabled Profiling kernel in Part 2 of this article). This version of the kernel contains the process and function identification routines, as well as the result-gathering and display routines. The process profiling approach also relies on a periodic interrupt from the OEM adaptation layer (OAL).

The profiler collects data as soon as it is started. When stopped, it analyzes the data and sends the results over the debug port.

Windows CE does not automatically start or stop the profiler. You can start and stop the profiler by having an application make calls to the ProfileStart and ProfileStop functions. You can also start and stop the profiler with the default keyboard driver, which supports keys for controlling the profiler. Also, you can use the prof command in the Target Control window to control the profiler.

To use the Monte Carlo Profiler tool from the Windows CE Target Control window, use the following commands:

  • prof on — Turns on profiling
  • s philo — Starts the Philo.exe application (the same application you used with the Remote Call Profiler tool)
  • prof off — Turns off profiling

Note   You should wait for the application to end before turning off the Monte Carlo Profiler tool.

The following is the output taken from running the profiler against the Philo.exe application.

Total samples recorded = 120814
Module        Hits        Percent
------------  ----------  -------
nk.exe            118695     98.2
coredll.dll          905      0.7
tcpstk.dll           226      0.1
afd.dll               52      0.0
ndis.dll              46      0.0
cxport.dll            26      0.0
relfsd.dll            20      0.0
Philo.exe             18      0.0
gwes.exe              15      0.0
VMini.dll             11      0.0
netbios.dll            7      0.0
filesys.exe            6      0.0
fsdmgr.dll             4      0.0
ddi.dll                4      0.0
explorer.exe           3      0.0
shell.exe              2      0.0
pm.dll                 1      0.0
commctrl.dll           1      0.0
tapi.dll               1      0.0
redir.dll              1      0.0
ohci2.dll              1      0.0
UNKNOWN              769      0.6

Hits       Percent Address  Module       Routine
---------- ------- -------- ------------:---------------------
113891    94.2 8055ab26 nk.exe      :_IDLE_STATE
   320     0.2 8054e977 nk.exe      :_WaitOneMore
   292     0.2 80549ca6 nk.exe      :_KCNextThread
   244     0.2 8054f292 nk.exe      :_SC_WaitForMultiple
   153     0.1 805451e6 nk.exe      :_RunqDequeue
   144     0.1 8054b2d4 nk.exe      :_SleepOneMore
   134     0.1 80540c88 nk.exe      :_memcpy
   133     0.1 805430a4 nk.exe      :_KCall
   120     0.0 03fd10a0 coredll.dll :_memset
   103     0.0 8054921b nk.exe      :_NextThread
   101     0.0 8054191f nk.exe      :_INTERRUPTS_ENABLE
   101     0.0 805430cd nk.exe      :_Int22KCallHandler
    98     0.0 80540c10 nk.exe      :_memset
     3     0.0 03f33e1b relfsd.dll  :_write_header
     3     0.0 03f343aa relfsd.dll  :_rreadnocs
     3     0.0 03de1090 fsdmgr.dll  :?ExitVolume
     3     0.0 03cc3a37 cxport.dll  :_CTEpEventThread
     3     0.0 03bc26d6 afd.dll     :_WsaBufToNdisBuf
     3     0.0 03bc5988 afd.dll     :_EnterCriticalSection
     3     0.0 03a5cf70 tcpstk.dll  :_InterlockedIncrement
     3     0.0 03a7990b tcpstk.dll  :_UDPRcv
     3     0.0 03a95e71 tcpstk.dll  :_GetAddrType
     3     0.0 00011915 Philo.exe   :?OutputDebug     3     0.0 00011ee3 Philo.exe   :?IsAvailable     3     0.0 0001257f Philo.exe   :?IsInhibitProfiling     2     0.0 00011018 Philo.exe   :?MyWaitForSingleObject     2     0.0 000120bf Philo.exe   :?CeCapInit     1     0.0 0001113a Philo.exe   :?MySleep     1     0.0 000114fa Philo.exe   :?Eat     1     0.0 000125c1 Philo.exe   :__penter
     1     0.0 02cb8b2c ohci2.dll   :?GetPortStatus
   773     0.6                      :<UNACCOUNTED FOR>

You can see from the profiling information that 94 percent of the time spent while the philo.exe application was running was spent in _IDLE_STATE.

Summary

The following is a summary of the exercises provided in this article:

  • Create a platform image
  • Enable the Profiling kernel and event tracking
  • Create and add the memLeak application to the platform
  • Create and add the GDILeak application to the platform
  • Create and add the Philosophers application to the platform
  • Configure the Philosophers application
  • Build the platform
  • Configure the debug and kernel transports
  • Download the operating system
  • Use the Remote Performance Monitor tool to monitor the current memory load
  • Run the memLeak application to show leaks on the Remote Performance Monitor
  • View debug zone information in the memLeak application
  • Use the Remote Kernel Tracker tool to view the current memory load
  • Stop the memLeak application
  • Start the Application Verifier tool
  • Examine the GDILeak.exe application's output from the Application Verifier tool
  • Open the Philosophers application with the Remote Call Profiler tool

Congratulations! You've completed all the exercises.