This [changing other vars] sounds like your basic buffer overrun. Make sure that your arrays have the right number of elements and check for the usual suspects (off-by-ones and so on). Also, be aware of using procedures such as FillChar or Move, since they can be risky. Here's a quick example:

[pascal][background=#FFFFFF][comment=#0000FF][normal=#000000][number=#C00000][reserved=#000000][string=#00C000]procedure TForm1.Button1Click(Sender: TObject);
var
y: integer;
x: array of integer;
begin
y := 23;
SetLength(x, 2);
FillChar(x, 8, 0);
ShowMessage(IntToStr(y));

ShowMessage(Format('addr1 is %x, addr2 is %x', [Integer(addr(x)), Integer(addr(y))]));
end;[/pascal]
Notice that the value of y has changed from 23 to 0! This is because the FillChar is doing too much (going over x, which is a pointer, for 8 bytes -- i.e. 4 bytes for x, which is essentially a pointer, and 4 bytes for y). The wanted change there would be to use x[0] with the FillChar to get correct results. Be careful of similar problems with pointers.

Avatar: ggs is talking about two different approaches to multitasking by cooperative vs pre-emptive. The first one relies on each task to say "I've had enough", which the second one yanks control away from a task as required. As a result, the second (pre-emptive) is much preferred as it's more reliable. I believe that Windows 3.1 had co-operative multitasking, which meant that a poorly written app could hog the system at the expense of other tasks. In later Windows, the task should be forced to take a back seat as required.