For your own projects, the best solution for this particular class of problems is to flag your constructors with the "explicit" keyword. This prevents the compiler from automagically creating instances of your classes.
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/vcrefExplicit.asp
Mintmaster said:
I'm surprised there wasn't a compiler warning.
This code compiles fine with /W4 /WX (which is the highest possible warning level, the default VC++ warning level is only /W3).
Just step through it in a debugger instead of speculating. You'll see what the compiler did with the crazy temporary CComBSTR firsthand.
Mintmaster said:
I know very little if anything about CComBSTR, but "" is clearly a temporary to me. Besides simultaneous character array declaration and initialization, does a string literal ever not create a temporary?
I may be missing something, but I don't see why all that casting business has anything to do with the error. You're returning the address of a temporary, and I've definately had VC++ warn me about that before.
Constant string literals defined in the body of your program all get stuck into the global .rdata section of your .EXE by the compiler,
they are not temporaries. Hence the compiler will not warn you about returning a temporary.
.rdata is a read-only section containing all the constants defined in your app. This is so if you have the same string literal multiple times in your app, the compiler only needs to keep a single copy around.
This is why code like this:
Code:
WCHAR* pwszFoo = L"abcde"; // declare a pointer to a string literal, perfectly legal
wprintf( pwszFoo ); // works just fine
pwszFoo[0] = L'!'; // now try to reset the first character to a !
is wrong, and will cause an AV: your app is trying to write a read-only section, and the OS will say "nuh-uh, can't do that, buh-bye", and your app will go poof.
(On some OSes without MMU support or good memory protection, the write may succeed, meaning you'll have corrupted memory. Your program will appear to work for a while, but you may have trashed your constants, which may or may not cause a mystifying crash sometime later on.)
Do a "link /dump /all foo.exe" and you will be able to see the names and contents of all the sections in your .EXE.
See
http://msdn.microsoft.com/msdnmag/issues/02/02/PE/default.aspx
and
http://msdn.microsoft.com/msdnmag/issues/02/03/PE2/default.aspx if you want more detail.
The problem is C++ is a very rich language, with very few safeguards built in, and an infinite number of ways to shoot yourself in the foot. With thermo-nuclear weapons.
The only solution is to either not use C++, or understand what's really going on underneath the covers in the compiler.
A lot of people try to use the object oriented features of C++ without understanding what's going on underneath, which inevitably leads to problems. A guy I know calls code written this way "object disoriented programming".