Last week, my leader had another annoying problem, a snippet like below is not working at all. The GetBool function will assign the 2nd argument “value” to true internally, while when returning, it is still false.
1: IMyNameValues src;
2:
3: ...
4:
5: if (destField == nullptr)
6: {
7: bool value;
8: System::String^ key = strConverter.Utf8ToString(srcField.Name);
9: mGuts->CheckCode(src.GetBool(srcField.Name, value));
10: dest->AddField(key, value);
11: }
12: else if (destField->Type->DotNetType->Equals(System::Boolean::typeid))
13: {
14: bool value;
15: const char* pName = srcField.Name;
16: mGuts->CheckCode((long)src.GetBool(srcField.Name, value));
17: dest->AddField(destField, value);
18: }
19:
20: ...
21:
22: //the GetBool function's signature is like:
23: long GetBool(const string& name, bool& value);
After debugging the codes, and found an interesting thing, the “&value” before entering the GetBool function is different from the one inside the function. Then, reading the disassembly code, and manually calculating the local variable address on the call stack (ebp + xxxx), it is really different from the actual address of the local variable.
Then, if I changed the name of the local variable “value”, making different for the if/else branches, and it works!
1: if (destField == nullptr)
2: {
3: bool value;
4: System::String^ key = strConverter.Utf8ToString(srcField.Name);
5: mGuts->CheckCode(src.GetBool(srcField.Name, value));
6: dest->AddField(key, value);
7: }
8: else if (destField->Type->DotNetType->Equals(System::Boolean::typeid))
9: {
10: bool value1;
11: const char* pName = srcField.Name;
12: mGuts->CheckCode((long)src.GetBool(srcField.Name, value1));
13: dest->AddField(destField, value1);
14: }
And if disabling compiler optimization, also fine. It seems to be a compiler optimization bug, And I tried to reproduce it with some sample small snippet, could not reproduce. Since the product codes are kind of over-designed, introducing too many unnecessary concepts, for instance, virtual inheritance, RTTI, CLI, and etc, also involving a bunch of mangled classes. I had no time to trim them to get a simple case.
Another simple solution is move the inner local variable forward, it also works, e.g.:
1: bool value;
2: if (destField == nullptr)
3: {
4: System::String^ key = strConverter.Utf8ToString(srcField.Name);
5: mGuts->CheckCode(src.GetBool(srcField.Name, value));
6: dest->AddField(key, value);
7: }
8: else if (destField->Type->DotNetType->Equals(System::Boolean::typeid))
9: {
10: const char* pName = srcField.Name;
11: mGuts->CheckCode((long)src.GetBool(srcField.Name, value));
12: dest->AddField(destField, value);
13: }