Hello fellow experts. I usually answer questions here but right now I have an odd situation and I wonder if anyone know how to get around it easily:
1. I have a class SString which implements a string type class similar to std::string but enough differences that I cannot easily change to std::string.
2. In some code I have a declaration like this:
SString a;
well actually, the variable isn't a but that ought to be irrelevant what the variable name is ;)
3. Checking the assembly code I have found that the compiler appear to be thinking along the lines like this:
a) I want to constract an object a using the default constructor. This is essentially a call to:
a.SString::SString();
which in g++ translates to a call to SString::SString(SString * const this) with a parameter of 'a', so:
SString::SString(& a);
Thus, the constructor get a pointer to the memory block where it should construct the new object.
However, here comes the snag.
b) g++ thinks that since sizeof(SString) == sizeof(void *) == sizeof(int) that it should appearantly treat the struct like a builtin type and transfer it by value. This is normally a good thing since that is what I normally want and it is exactly why the SString type is designed the way it is - I normally do want transfer by value and that the type is treated like a builtin type.
Therefore, instead of transferring a pointer to a, the call transfers the value of a, which happens to be the value stored where the pointer to the string would be stored when the object is constructed. Since the object isn't constructed yet, the data transferred to the constructor is just random garbage. That should be ok since the constructor is to construct a value anyway and transfer it back so you can overwrite that random garbage with a new value.
c) Problem is that the constructor appear to be completely ignorant about the "transfer by value" choice made at the call and assumes that the constructor always get a pointer to the object as argument.
d) The result is that the random garbage value is then taken as the pointer to where the SString object should be constructed and the constructor returns.
e) The caller appear to have forgotten that it transferred the string object by value to a constructor and therefore ought to store a constructed value in its place and moves happily along with garbage value in the SString object.
I would assume that the "transfer by value" is normally a good thing BUT NOT IN A CONSTRUCTOR. It should therefore have been disabled for those and it should have taken the address of the object and called the constructor. This is obviously what the constructor code appear to assume and this is what it should have done.
I believe this is a clear example of a bug in g++. gcc --version displays:
$ gcc --version
gcc (GCC) 3.2.2 20030222 (Red Hat Linux 3.2.2-5)
Copyright (C) 2002 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Question: Does anyone know of a workaround for this bug?
No, I cannot change to std::string. That would imply a major overhaul of the program and the program is around 200k lines and I am not going to do that in the near future. We do have plans to switch to STL but not for the immediate future.
Although I can do it, I am VERY reluctant to include phony elements in the SString class just to make it so large that the "transfer by value" semantics is not used. In fact I carefully crafted the class exactly because I want it to use that semantics for the major part of the program. The SString class is used many places and stored and copied around and a transfer by value means that things are faster and simpler than if a traditional transfer by pointer semantics is in use. I would very much welcome some option or trick to force the compiler to disable transfer by value semantics for constructors though. It is obvious that the constructors assume that such semantics is disabled for them, it's just that the caller appear to not be aware of handling constructors any different from any others.
If anyone can point me to where in the gcc source this decision is made so that I can either apply a bug fix or fix it myself, that too, would be welcome.
Thank you in advance for any help you can provide.
Alf