The ESP8266 has precious little RAM. You start with a little over 80KB, but the system takes up over 20K of that just for wifi and other required functionality. So best case you get under 60K of RAM for your use. In fact, if you use the Arduino toolchain you’ll be lucky to be left with 30K.
Lots of things you wouldn’t expect use up that RAM. If you’re using C++ and have virtual classes, each one will have a vtable, a little hidden piece of RAM that has pointers to virtual functions. That doesn’t mean you shouldn’t use C++ or even virtual functions. You just need to take care to minimize the number of virtual functions you use.
String constants are typically the biggest offenders. Since they’re constants, you’d think they would go into Flash. But on the Esp Flash memory has access restrictions. You have to access memory on 4 byte boundaries. Attempting to access the bytes of a string stored in Flash would cause a crash. Other data structures like constant arrays used for initialization go into RAM as well. If you’re not careful, you’ll use up all that precious RAM before executing a line of code.
It’s easy to specify that a string or other data structure go into Flash, but I’ve seen a lot of confusion about how to access this memory, so I’ll try to clarify.