Wednesday, February 6, 2013

String::Format in C++Builder

If you are writing C++ using the VCL there is a potential problem. Something like:
TVarRec array[] = { .... };
String s = String::Format("....", EXISTINGARRAY(array));
The problem is that a TVarRec initialised with a string doesn't hold the string, only a void* pointer to its data. So if you create any temp strings in the array they may be destroyed before String::Format runs. For example:
TVarRec array[] = { Edit1->Text };
Caption = String::Format("Hi %s", EXISTINGARRAY(array));
Here, Edit1->Text is not a 'real' string, it's a property which calls GetText, which creates a string on the fly. This is destroyed almost straight away, leaving array with a dangling pointer. The solution is to make sure the lifetime of the string extends past the Format, i.e.
String txt = Edit1->Text;
TVarRec array[] = { txt };
Caption = String::Format("Hi %s", EXISTINGARRAY(array));
So in that case you might as well use ARRAYOFCONST, i.e.
String txt = Edit1->Text;
Caption = String::Format("Hi %s", ARRAYOFCONST((txt)));