First question is: What version of Turbo Pascal? This could make a great difference. For instance, in ver 6 and earlier, the editor would only hold 64K of text, limiting the size of programs, and causing the need to break up code into sometimes non-intuitive chunks.
Also, the order of entry/exit of units is like this: First unit initializes, (possibly) causing other units to initialize in turn. During finalization (exit), the unit code is executed in the reverse of the initialization. It's basically like a big stack that's pushed on init, and popped on finalization.
This could be the source of some of your problems. Unit finalization is always executed, even if it's not explicitly coded. As you can tell by re-arranging the units and getting different symptoms. Slightly off-topic: One of the interesting things about units is that you cannot have circular unit references in the interface section, but you are allowed circular unit references in the implementation section. Sometimes, moving units that are not absolutely needed at the top, to the bottom of the unit solves many problems.
Use your debugger. You might have to start stepping from the very beginning of your program. If it's heavily object-oriented, this can be a true pain. Judicious use of breakpoints helps, if you can figure out where to set them. The technique known as "half-stepping" helps tremendously here.
The differences in program exit behavior can be attributed to the different versions of OSs you've run the program on. WinXP does a much better job of "virtualizing" programs so that, if something goes wrong in one program's memory space, that program can be killed and the memory reclaimed without crashing the entire machine. Mostly this works. Win98 is much more primitive, and the "This program has performed an illegal operation..." message is about as generic as you can get, and provides no real help in diagnosing a problem. You may also end up crashing the machine.
DOS (as in versions 2.1 to 6.2), on the other hand, is so primitive that it's quite robust. Sometimes, you might actually have a problem with a program, but have no idea what, or even that a problem exists.
So, to sum up:
- Break your main program into smaller chunks (units).
- Re-arrange your units.
- Use the debugger to step through to the spot where things break. Sometimes having just this little piece of information answers all kinds of questions.
I hope some of this helps, but without having slightly more information to go on, all I can offer is generalities.
Daaave