Saturday, September 10, 2011

Hard-to-find object variable overwriting issue

I write software programs in Delphi, version 7 (also in C++ Builder, but this post is about Delphi). Once I decided to optimize the code and to add "const" specifier to all parameter declarations of methods which are not changed in the method body itself. This is recommended for better readability and for performance reasons. For variables of WideString type, if you do not use "const" specifier in function parameters list, the compiler will create new copy of  passed WideString variable upon function entry and release it after function will return. This is because WideStrings are not reference-counted, as opposed to AnsiStrings. But when "const" is specified, the compiler passes pointer to string content (2-byte-wide chars) as is. So, I added "const" specifier everywhere when applicable, and did not receive any copiler warning. But during following testing, it turned out that something had became broken after this change. Strange error sometimes appears, which resulted in wrong value in some object field of type WideString. This error did not appear always, and only on one of two tested MS Windows versions.
I started to seek for the reason, and finally it traced to using WideString-type field of the object which passed as now "const" parameter. The code was something like:

procedure TFoo.SetProperty(const APropValue: WideString);
...
begin
...
  FPropValue := APropValue;
end;

....

procedure TFoo.DoSomething(const APropValue: WideString;...);
...
begin
...
  SetProperty(APropValue);
  DoSomethingElse(APropValue);
end;

procedure TFoo.DoSomething2(...);
...
begin
...
  DoSomething(FPropValue);
...
end;


The compiler did not detect any issues, yet the problem was
that after invoking of SetProperty, the previous pointer to WideChars array contained in FPropValue field, and in APropValue parameter, becomes invalid, but this old pointer value was used when invoking DoSomethingElse method.
I fixed the problem by eliminating "const" specifier from DoSomething declaration.

Be aware of such a pitfall!

No comments:

Post a Comment