^Pchar 指向 PChar 数组的指针
Pointer of ^Pchar to array of PChar
当我从 Delphi 6 迁移到 Delphi 10.2 东京
当我尝试将 ^PChar 的指针转换为 PChar
数组时出现错误
type
PServEnt = ^TServEnt;
TServEnt = packed record
s_name: PChar; // official service name
s_aliases: ^PChar; // alias list
s_port: Smallint; // protocol to use
s_proto: PChar; // port #
end;
function TIdStackWindows.WSGetServByPort(
const APortNumber: Integer): TIdStrings;
var
ps: PServEnt;
i: integer;
p: array of PChar;
begin
Result := TIdStringList.Create;
p := nil;
try
ps := GetServByPort(HToNs(APortNumber), nil);
if ps <> nil then
begin
Result.Add(ps^.s_name);
i := 0;
p := Pointer(ps^.s_aliases); // get error Incompatible types: 'Dynamic array' and 'Pointer'
while p[i] <> nil do
begin
Result.Add(PChar(p[i]));
inc(i);
end;
end;
except
Result.Free;
end;
end;
此代码在 Delphi 2010 中运行良好,如何在 Delphi 10.2 Tokyo
中使其正确
错误信息是正确的,如果代码在早期版本Delphi中编译,那是因为早期版本的编译器有缺陷。
动态数组不仅仅是指向第一个元素的指针。它还封装了存储数组长度和引用计数的元数据。因此,您的演员阵容无效。你逃脱了这个无效代码,因为你没有尝试访问这个元数据,但这既是偶然的,也是有意的。
不要尝试转换为动态数组。而是使用指针算法。例如:
function TIdStackWindows.WSGetServByPort(
const APortNumber: Integer): TIdStrings;
var
ps: PServEnt;
p: PPChar;
begin
Result := TIdStringList.Create;
try
ps := GetServByPort(HToNs(APortNumber), nil);
if ps <> nil then
begin
Result.Add(ps^.s_name);
p := PPChar(ps^.s_aliases); // cast needed due to Indy record type's use of un-nameable type
while p^ <> nil do
begin
Result.Add(p^);
inc(p);
end;
end;
except
Result.Free;
raise;
end;
end;
我将别名列表的类型声明更改为PPChar
以避免在分配给该类型的局部变量时出现不兼容的类型错误。
另请注意,我已更正您的异常处理,该异常处理之前吞并异常并返回无效的对象引用。
当我从 Delphi 6 迁移到 Delphi 10.2 东京 当我尝试将 ^PChar 的指针转换为 PChar
数组时出现错误type
PServEnt = ^TServEnt;
TServEnt = packed record
s_name: PChar; // official service name
s_aliases: ^PChar; // alias list
s_port: Smallint; // protocol to use
s_proto: PChar; // port #
end;
function TIdStackWindows.WSGetServByPort(
const APortNumber: Integer): TIdStrings;
var
ps: PServEnt;
i: integer;
p: array of PChar;
begin
Result := TIdStringList.Create;
p := nil;
try
ps := GetServByPort(HToNs(APortNumber), nil);
if ps <> nil then
begin
Result.Add(ps^.s_name);
i := 0;
p := Pointer(ps^.s_aliases); // get error Incompatible types: 'Dynamic array' and 'Pointer'
while p[i] <> nil do
begin
Result.Add(PChar(p[i]));
inc(i);
end;
end;
except
Result.Free;
end;
end;
此代码在 Delphi 2010 中运行良好,如何在 Delphi 10.2 Tokyo
中使其正确错误信息是正确的,如果代码在早期版本Delphi中编译,那是因为早期版本的编译器有缺陷。
动态数组不仅仅是指向第一个元素的指针。它还封装了存储数组长度和引用计数的元数据。因此,您的演员阵容无效。你逃脱了这个无效代码,因为你没有尝试访问这个元数据,但这既是偶然的,也是有意的。
不要尝试转换为动态数组。而是使用指针算法。例如:
function TIdStackWindows.WSGetServByPort(
const APortNumber: Integer): TIdStrings;
var
ps: PServEnt;
p: PPChar;
begin
Result := TIdStringList.Create;
try
ps := GetServByPort(HToNs(APortNumber), nil);
if ps <> nil then
begin
Result.Add(ps^.s_name);
p := PPChar(ps^.s_aliases); // cast needed due to Indy record type's use of un-nameable type
while p^ <> nil do
begin
Result.Add(p^);
inc(p);
end;
end;
except
Result.Free;
raise;
end;
end;
我将别名列表的类型声明更改为PPChar
以避免在分配给该类型的局部变量时出现不兼容的类型错误。
另请注意,我已更正您的异常处理,该异常处理之前吞并异常并返回无效的对象引用。