Avoiding Movement Problems

We have been creating small Windows programs for several chapters now and have not run into problems when Windows has moved the code and data segments in memory. Here are some general rules for continuing to avoid problems:

Use the small model or medium model.

Don't declare any variables as far. For instance, don't do something like this:

int far array [10][1000] ; // Bad!!!!!

This code creates a second data segment in your program. Unless you mark this segment as fixed, Windows does not properly handle references to this array.

Don't store any far pointers to data except those that Windows gives you. The lpszCmdLine parameter passed to WinMain is OK. The far addresses returned from GlobalLock (discussed later in this chapter) and LockResource (discussed in Chapter 8) point to fixed data until you specifically unlock the data, so these are legitimate also. Some window messages (WM_CREATE, for instance) have lParam values that are far pointers. Use these pointers only for the duration of the message.

When you call Windows functions, you must often pass far pointers to data that are within your data segment. But don't declare far pointers and assign them far addresses to local data items and then later use the far pointers when calling Windows functions. Instead, cast the near pointers into far pointers when you call the functions, or let the compiler do this casting for you.

Don't store or use any far pointers to code, except for pointers to functions that are specifically declared as far or far pointers returned from MakeProcInstance. (Pointers to functions in medium-model programs are also OK.)

When you need to give Windows a far pointer to a function for a call-back function (as discussed in Chapter 5), a window subclassing function (as discussed in Chapter 6), or a dialog box function (as discussed in Chapter 10), obtain the pointer from MakeProcInstance. The function must be declared as FAR PASCAL and included in the EXPORTS section of your module definition file.

Although these rules are numerous and important, don't let them drive you to paranoia. Keep in mind that Windows is nonpreemptive. Windows will not pull the rug out from under you by interrupting your code. Windows will move or discard your code segments only when you make a Windows call. Windows will not move your data segment except when you make a few select Windows calls. If you have a long stretch of code between two Windows calls, you can be as carefree as you like in that code without worrying about sudden movements.