I would adviceadvise you to also turn off any debugging information, even if it doesn't leak any majorly important information today it might do so tomorrow. The amount of information leakage from the debug information varies from compiler to compiler and from binary format to binary format. For instance, Microsoft Visual C++ keeps all important debugging information in an external database, usually in the form of a PDB. The most you might leak is the path you used when building your software.
When it comes to strings you should definitely encrypt them if you need them at all. I would aim to replace all the ones that are for error tracing and error logging with numeric enumerations. Strings whichthat reveal any sort of information about what is going on right now in your binary needsneed to be unavailable. If you encrypt the strings, they will be decrypted. Try to avoid them as much as possible.
Another strong source of information leakage is imports of system APIs. You want to make sure that any imported function which has a known signature is well-hidden and can not be found using automatic analysis. So an array of function pointers from something like LoadLibrary/GetProcAddress is out of the question. All calls to imported functions need to go through a one way-way function and needsneed to be embedded within an obfuscated block.
You should also cover any critical code with some sort of heavy obfuscation. Some of the heavier and cheaper obfuscations right now are CodeVirtualizer/Themida and VMProtect. Be aware that these packages have an abundance of defects though. They will sometimes transform your code to something which will not be the equivalent of the original which can lead to instability. They also slow down the obfuscated code significantly. A factor of 10000 times slower is not uncommon. There's also the issue of triggering more false positives with anti-virus software. I would adviceadvise you to sign your software using a reputable certificate authority.
The separation of code into functions is another thing whichthat makes it easier to reverse engineer-engineer a program. This applies especially when the functions are obfuscated because it creates boundaries around which the reverse engineer can reason about your software. This way the reverse engineer can solve your program in a divide and conquer-and-conquer manner. Ideally, you would want your software in one effective block with obfuscation applied uniformly to the entire block as one. SoTo reduce the number of blocks, use inlining very generously and wrap them in a good obfuscation algorithm. The compiler can easily do some heavy optimizations and stack ordering which will make the block harder to reverse engineer.
If you're designing a copy protection system prepare for it to be broken mentally. Make sure you have a plan for how you will deal with the break and how to make sure the next version of your software adds enough value to drive upgrades. Build your system on a solid ground which can not be broken, do not resort to generating your own license keys using some custom algorithm hidden in the manner I described above. The system needs to be built on a sound cryptographic foundation for the unforgeability of messages.