一个遗留的老项目,原来是在Delphi 6(D6)环境下开发和编译的。这两天计划将其迁移到Delphi 7(D7)下,结果使用D7编译后的新程序不能正常运行,出现某些界面打不开的情况。经跟踪测试发现原来在D6下可正常执行的代码在D7中发生了“死循环”的情况。
D6与D7版本之间的差异应该说还是比较小的,怎么会出现这种情况呢?查阅了D7的What’s New文档,终于找到了缘由。
原来在出错的代码段中使用了常见的系统字符串函数LeftStr、RightStr。根据文档说明,D7中修改了它们的实现,目的是为了支持多字节字符集,比如汉字。除了以上两个函数外,还包括一个MidStr。
这一组字符串函数的功能是取字符串的子串,位于StrUtils单元。在D6中,他们只有一种实现,参数与返回值类型都是String(默认为AnsiString)。而在D7中,分别有单字节和多字节两种实现,即AnsiString和WideString版本。这样,如果参数中存在汉字或全角符号等双字节的字符,会自动调用到WideString版本,从而导致出现了不希望的结果。
打开StrUtils单元,比较D6和D7的对应部分,一目了然。(以LeftStr为例)
D6
- function LeftStr(const AText: string; const ACount: Integer): string;
- begin
- Result := Copy(AText, 1, ACount);
- end;
D7
- function LeftStr(const AText: string; const ACount: Integer): string;
- begin
- Result := Copy(AText, 1, ACount);
- end;
- function LeftStr(const AText: WideString; const ACount: Integer): WideString; overload;
- begin
- Result := Copy(AText, 1, ACount);
- end;
- function LeftBStr(const AText: AnsiString; const AByteCount: Integer): AnsiString;
- begin
- Result := Copy(AText, 1, AByteCount);
- end;
- function AnsiLeftStr(const AText: AnsiString; const ACount: Integer): AnsiString;
- begin
- Result := LeftStr(AText, ACount);
- end;
举例说明:
ShowMessage( LeftStr(‘中华人民共和国’, 2));
同样一行代码在D6中将会显示“中”,D7中显示“中华”。
但如果参数不含有多字节字符,全部是单字节字符,则不会有问题。
如:
ShowMessage( LeftStr(‘China’, 2));
在D6和D7中都将显示“Ch”。
那么,如果代码中大量使用了以上三个字符串函数,在迁移时如何处理呢?
实际上Delphi的工程师们已经为我们准备好了保持兼容的简单方法。那就是为上述三个函数准备了对应的兼容版本,名称分别为LeftBStr、RightBStr和MidBStr。也就是说,只要将原有代码中的LeftStr、RightStr和MidStr分别作替换即可。当然,如果确定这些函数仅可能会处理单字节字符,则可以不作任何变动。
更多细节及迁移到D7的注意事项可参见《What’s New in Delphi 7》文档。