When programs don't work

I have several times now added a small bit of simple code to a functioning program only to have it stop working or behave strangely. Things as simple as adding one more Serial.println("some debug information") are enough to do it. Adding one more include file even without using it also can doom a functioning program.

The afflicted sketches are still under the 7k size limit, I suspect I might be overflowing RAM.

How would one know they have overflowed RAM? I assume we have a data segment at one end and a stack at the other, I further guess that the data segment must be copied in from the program memory, so there might be a clever binutils command to query the data segment size from the ELF file, but that still leaves stack requirements as a mystery.

Even more basic... I noticed in the bootcloner code a special keyword to make a constant stay in program space. Does the lack of this on our string constants mean they are copied into RAM?

I'll start digging into the generated binaries looking for answers, but any help from people that know would be appreciated.

I found a nice resource on the avr-gcc code generation in the avr-libc manual.
http://www.nongnu.org/avr-libc/user-manual/index.html
Their FAQ leads to all sorts of interesting facts about code size optimization and keeping strings out of RAM.