My app is compiled with Delphi 2010. That app loads a Delphi 7 compiled DLL which loads a Delphi 2010 compiled DLL.
D2010 app LOADS D7 DLL LOADS D2010 DLL
The exported functions of the D7 DLL uses Widestrings
and the exported functions of the Delphi 2010 DLL use strings
.
As we all know, strings
in Delphi 2010 are Unicode (2 bytes) and in Delphi 7 they are Ansi (1 byte).
All my tests show me that it is working despite the fact that it should not. I am wondering:
Why is it working?
What can go wrong?
Which memory manager should I use (Delphi 2010 or Delphi 7 memory manager DLL)
In D2009 and D2010, the RTL has logic in place (the compiler's {$STRINGCHECKS ON}
directive) that allows an AnsiString
to receive a Unicode payload, and a UnicodeString
to receive an Ansi payload, across module boundaries, and then to perform a silent inline data conversion to the correct string type when the AnsiString
/UnicodeString
data is accessed. This is primarily to support legacy C++ projects that use event handlers with AnsiString
parameters on the C++ side and UnicodeString
variables on the Delphi side. In this case, it could also allow the D7 DLL to pass Ansi data to the D2010 DLL (the STRINGCHECKS
directive was removed in XE, though).
I would expect the D2010 DLL to fail, though, because the memory layout of a StrRec
record (which preceeds the character data in memory) changed in D2009 to add support for codepages, so the D7 DLL would not be allocating a D2010-compatible StrRec
when passing an AnsiString
value to a UnicodeString
parameter in the D2010 DLL. I would expect the D2010 DLL to crash when it tries to access/free memory that does not exist.
This is yet another argument against ever passing String
types across DLL boundaries. Just don't do it, ever. Use WideString
or PAnsiChar
/PWideChar
instead.