We've just slogged through several articles composed of scenarios, rules, warnings, and fairly druid memory management. Now, it's time for something a bit more tangible. First of all, you'll find it a bit reassuring to remember these two things: Most of the time just being well informed about "best practices" in memory allocation will keep you out of trouble. Second, there are some tools you can use to proactively assess the allocation status of memory. The Memory Dialog example shows you how to check the physical page size of a device, how to get a reliable ballpark estimate of memory usage status, and how to get a "read-in-place" pointer to string resources.
Figure 3: The Memory Dialog Example
The main source file for MemoryDialog is provided in an accompanying file.
The real business of the MemoryDialog Example is handled in—you guessed it—the dialog procedure, MemStatusDlgProc(). Here we employ two very useful functions for gathering information about the state of memory: GetSystemInfo() and GlobalMemoryStatus(). Here's how to use GetSystemInfo() to find the page size on a CE device:
memset(&siSysInfo, 0x0, sizeof( siSysInfo) ); GetSystemInfo( (LPSYSTEM_INFO)&siSysInfo ); _stprintf( szBuff, TEXT(" %s : %i"), TEXT("Page Size"), siSysInfo.dwPageSize );
The single parameter to GetSystemInfo() is the SYSTEM_INFO structure. Notice that we explicitly initialize this structure before passing it as a parameter. This is especially important in the context of the MemoryDialog example program, because the siSysInfo is allocated on the stack. If we don't explicitly clear its space, it will be passed containing all sorts of random leftovers which could confuse us later. The only returned information of which we make use in this example is siSysInfo.dwPageSize, (however, you can get a great deal of other information from this structure, including processor architecture, version and stepping level). If you plan to make memory allocations using VirtualAlloc() or HeapCreate(), use siSysInfo.dwPageSize to optimize allocation requests to match page size multiples of the device.
Estimating Available Memory
You can get a fairly good, but rough, estimate of current memory use with GlobalMemoryStatus(). Here's a code fragment that shows how to get a percentage estimate of memory in use:
memset(&msMemStats, 0x0, sizeof( msMemStats) ); msMemStats.dwLength = sizeof( msMemStats); GlobalMemoryStatus( (LPMEMORYSTATUS)&msMemStats ); _stprintf( szBuff, TEXT(" %s "), TEXT("% Memory in use")); ListBox_InsertString(hWndList, -1, &szBuff);
Unfortunately, this is call is limited by the fact that it only provides a "snapshot" of memory use at application load time, so don't rely on it to make critical allocation decisions dynamically. Also, not the use of the _stprintf() function used to format the listbox strings—this version handles the wide character strings used by CE controls.
In the last several examples, we analyzed the great importance of memory management under CE. Adapting memory usage is the first, most critical step in converting a Win32 application's functionality. Now, its time to think more deeply about porting the essential suite of application's other behaviors. As you've seen in our examinations of memory management, the biggest difference between porting application appearance and porting application behavior is that behaviors compete for use of shared system resources: memory, I/O capacity, and power. For this reason, porting behaviors isn't simply a matter of eliminating unsupported Win 32 APIs; it's more a matter of finding the most succinct and frugal ways to accomplish a particular task.
The first step in this process, and one that you must undertake entirely on your own, away from your workstation, is to identify the essence of the application you are porting. At the most basic practical level, there are two questions to ask:
- What task do you want to enable the user to accomplish?
- What product will the user's effort produce?
If you can answer these two questions very specifically, then you have a blueprint for porting critical behaviors. I would encourage you to write the answers to these questions, and if you work with a team, extend this exercise to everyone involved in managing the porting process. Notice that I suggest specifically excluding users and junior programming team members from this deliberation. Some things in life don't lend themselves to group decision-making, and porting code from Win 32 to the resource constrained environment of Windows CE is certainly in this category
Defining the functional essence of your application and its intended products constitutes an implicit determination about what Win32 behaviors and features are superfluous under Windows CE. This is probably the most critical task in porting to Win CE, and it is very, very difficult to accomplish. What makes it hard is that it implies wholesale abandonment of large chunks of your application's Win 32 code base, and it is human nature to resist letting go of that which you worked hard to create. If you try to define the scope of your Win CE app with too large a group or with people who are technically naïve, you'll find features creeping into your Win CE product design that just shouldn't be there.
In this spirit of "Heave ho!", I'll describe my own porting experiences and opinions in future examples, and of course, you may disagree. But more often than not, when I have had great difficulty implementing a feature on CE, a few hours away from the problem usually brought me to the realization that the feature was inappropriate or my design was too complex.
Just as in the previous articles, the object of the discussions in the next several will be to help you make steady, incremental progress toward a stable Windows CE implementation of your Win 32 code. To accomplish this as quickly as possible, we'll focus on code reuse rather than on using the new and unique features of Windows CE to implement your application's behaviors.
About the Author
Nancy Nicolaisen is a software engineer who has designed and implemented highly modular Windows CE products that include features such as full remote diagnostics, CE-side data compression, dynamically constructed user interface, automatic screen size detection, entry time data validation.
In addition to writing for Developer.com, she has written several books including Making Win 32 Applications Mobile.
# # #