Termination Handler Syntax
Windows Embedded CE supports termination handling. As a Microsoft extension to the C and C++ languages, it enables you to guarantee that the system always runs a certain block of code not matter how the flow of control leaves the guarded code block. This code section is called a termination handler, and is used to perform cleanup tasks even if an exception or some other error occurs in the guarded code. For example, you can use a termination handler to close thread handles that are no longer needed.
The following code fragment illustrates how to use the __try and __finally keywords for structured exception handling:
__try {
// Place guarded code here.
} __finally {
// Place termination code here.
}
Termination handling supports the __leave keyword within the guarded section. This keyword ends thread execution at the current position in the guarded section and resumes thread execution at the first statement in the termination handler without unwinding the call stack.
NOTE
Using __try, __except, and __finally blocks
A single __try block cannot have both an exception handler and a termination handler. If you must use both __except and __finally, use an outer try-except statement and an inner try-finally statement.
Dynamic Memory Allocation
Dynamic memory allocation is an allocation technique that relies on structured exception handling to minimize the total number of committed memory pages on the system. This is particularly useful if you must perform large memory allocations. Precommitting an entire allocation can cause the system to run out of committable pages and result in virtual memory allocation failures.
The dynamic memory allocation technique is as follows:
1. Call VirtualAlloc with a base address of NULL to reserve a block of memory. The system reserves this memory block without committing the pages.
2. Try to access a memory page. This raises an exception because you cannot read from or write to a non-committed page. This illegal operation results in a page fault exception. Figure 3-5 and Figure 3-6 show the outcome of an unhandled page fault in an application called PageFault.exe.
3. Implement an exception handler based on a filter function. Commit a page in the filter function from the reserved region. If successful, return EXCEPTION_CONTINUE_EXECUTION to continue thread execution in the __try block at the point where the exception occurred. If the page allocation failed, return EXCEPTION_EXECUTE_HANDLER to invoke the exception handler in the __except block and release the entire region of reserved and committed pages.
Figure 3-5An unhandled page fault exception from a user's perspective
Figure 3-6An unhandled page fault exception's debug output over KITL in Visual Studio 2005
The following code snippet illustrates the dynamic memory allocation technique based on page fault exception handling:
#define PAGESTOTAL 42 // Max. number of pages
LPTSTR lpPage; // Page to commit
DWORD dwPageSize; // Page size, in bytes
INT ExceptionFilter(DWORD dwCode) {
LPVOID lpvPage;
if (EXCEPTION_ACCESS_VIOLATION != dwCode) {
// This is an unexpected exception!
// Do not return EXCEPTION_EXECUTE_HANDLER
// to handle this in the application process.
// Instead, let the operating system handle it.
return EXCEPTION_CONTINUE_SEARCH;
}
// Allocate page for read/write access.
lpvPage = VirtualAlloc((LPVOID) lpPage,
dwPageSize, MEM_COMMIT, PAGE_READWRITE);
if (NULL == lpvPage) {
// Continue thread execution
// in __except block.
return EXCEPTION_EXECUTE_HANDLER;
}
// Set lpPage to the next page.
lpPage = (LPTSTR) ((PCHAR) lpPage + dwPageSize);
// Continue thread execution in __try block.
return EXCEPTION_CONTINUE_EXECUTION;
}
VOID DynamicVirtualAlloc() {
LPVOID lpvMem;
LPTSTR lpPtr;
DWORD i;
BOOL bRet;
// Get page size on computer.
SYSTEM_INFO sSysInfo;
GetSystemInfo(&sSysInfo);
dwPageSize = sSysInfo.dwPageSize;
// Reserve memory pages without committing.
lpvMem = VirtualAlloc(NULL, PAGESTOTAL*dwPageSize,
MEM_RESERVE, PAGE_NOACCESS);
lpPtr = lpPage = (LPTSTR) lpvMem;
// Use structured exception handling when accessing the pages.
for (i=0; i < PAGESTOTAL*dwPageSize; i++) {
__try {
// Write to memory.
lpPtr[i] = 'x';
} __except (ExceptionFilter(GetExceptionCode())) {
// Filter function unsuccessful. Abort mission.
ExitProcess( GetLastError() );
}
}
// Release the memory.
bRet = VirtualFree(lpvMem, 0, MEM_RELEASE);
}
Windows Embedded CE supports exception handling and termination handling natively. Exceptions in the processor, operating system, and applications are raised in response to improper instruction sequences, attempts to access an unavailable memory address, inaccessible device resources, invalid parameters, or any other operation that requires special processing, such as dynamic memory allocations. You can use try-except statements to react to error conditions outside the normal flow of control and try-finally statements to run code no matter how the flow of control leaves the guarded __try code block.
Exception handling supports filtering expressions and filtering functions, which enable you to control how you respond to raised events. It is not advisable to catch all exceptions because unexpected application behavior can be the result of malicious code. Only handle those exceptions that need to be dealt with directly for reliable and robust application behavior. The operating system can forward any unhandled exceptions to a postmortem debugger to create a memory dump and terminate the application.
EXAM TIP
To pass the certification exam, make sure you understand how to use exception handling and termination handling in Windows Embedded CE 6.0 R2.
Lesson 5: Implementing Power Management
Power management is essential for Windows Embedded CE devices. By lowering power consumption, you extend battery life and ensure a long-lasting, positive user experience. This is the ultimate goal of power management on portable devices. Stationary devices also benefit from power management. Regardless of equipment size, you can reduce operating costs, heat dissipation, mechanical wear and tear, and noise levels if you switch the device into a low-power state after a period of inactivity. And of course, implementing effective power-management features helps to lessen the burden on our environment.
Читать дальше