- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
请考虑以下程序:
program SO41175184;
{$APPTYPE CONSOLE}
uses
SysUtils;
function Int9999: PAnsiChar;
begin
Result := PAnsiChar(AnsiString(IntToStr(9999)));
end;
function Int99999: PAnsiChar;
begin
Result := PAnsiChar(AnsiString(IntToStr(99999)));
end;
function Int999999: PAnsiChar;
begin
Result := PAnsiChar(AnsiString(IntToStr(999999)));
end;
function Str9999: PAnsiChar;
begin
Result := PAnsiChar(AnsiString('9999'));
end;
function Str99999: PAnsiChar;
begin
Result := PAnsiChar(AnsiString('99999'));
end;
function Str999999: PAnsiChar;
begin
Result := PAnsiChar(AnsiString('999999'));
end;
begin
WriteLn(Int9999); // '9999'
WriteLn(Int99999); // '99999'
WriteLn(Int999999); // '999999'
WriteLn(string(AnsiString(Str9999))); // '9999'
WriteLn(string(AnsiString(Str99999))); // '99999'
WriteLn(string(AnsiString(Str999999))); // '999999'
WriteLn(string(AnsiString(PAnsiChar(AnsiString(IntToStr(9999)))))); // '9999'
WriteLn(string(AnsiString(PAnsiChar(AnsiString(IntToStr(99999)))))); // '99999'
WriteLn(string(AnsiString(PAnsiChar(AnsiString(IntToStr(999999)))))); // '999999'
WriteLn(string(AnsiString(Int9999))); // '9999'
WriteLn(string(AnsiString(Int99999))); // '9999' <----- ?!
WriteLn(string(AnsiString(Int999999))); // '999999'
ReadLn;
end.
只有在其中一种情况下,字符串才会丢失单个字符,在 Delphi 2010 和 Delphi XE3 中都是如此。对于 FPC,相同的程序可以正常工作。切换到 PChar
也会使问题消失。
我认为这与内存管理有关,但我没有足够的线索去哪里进行有意义的调查。谁能解释一下吗?
最佳答案
动态创建的字符串会进行引用计数,并在没有引用剩余时释放。
Result := PAnsiChar(AnsiString(IntToStr(99999)));
导致创建临时AnsiString
,其地址通过转换为PAnsiChar
获取,然后释放临时字符串†。生成的指针指向现在未声明的内存,该内存可能会因几乎任何原因而被覆盖,包括在分配更多字符串期间。
默认情况下,Delphi 和 FPC 都不会在释放期间清除内存,因此,如果内存尚未重新使用,那么在读取曾经存在的内容时,您可能会很幸运。或者,正如您所看到的,您可能不会。
当像这样返回PAnsiChar
时,调用者和被调用者之间需要就内存管理达成一致。您需要确保不会过早释放内存,并且您需要确保调用者知道如何在之后释放内存。
† Remy Lebeau 指出,这种释放发生在过程或函数返回时。如果在对 Result
赋值之后还有其他语句,则该字符串仍然可用。这通常是正确的,但也有一些情况是临时字符串在返回之前被释放,例如当您在循环中创建临时字符串时。我不建议在创建临时对象的语句结束后使用临时对象,即使它是有效的,因为这使得验证代码是否正确变得非常困难。对于这些情况,只需使用显式变量即可。
关于delphi - 为什么这个 PAnsiChar 在转换为 AnsiString 时会被截断?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41175184/
我使用以下方法将名为“TmpData”的字节数组转换为 PAnsiChar: PAnsiChar(@TmpData[0]); 但有些数据有换行符。如何删除换行符?请看下图 最佳答案 请注意,在下面的答
这些是 C DLL 函数示例及其 Delphi 翻译: C 定义: DLL_EXPORT int AR_dll_function (const char *terminal_no, const cha
我正在 Delphi XE2 中编译我的应用程序。它是在 delphi 7 中开发的。我的代码如下: type Name = array[0..100] of PChar; PName = ^Na
当我尝试将字符串从 TMemo 控件的 Lines 传递到 PChar 数组时,出现了一些奇怪的情况。在例程结束时,数组中的最后一个字符串将被复制。我能够用这个简单的代码复制这个: procedure
这个问题已经有答案了: What is the difference between WideChar and AnsiChar? (2 个回答) 已关闭 8 年前。 我是delphi XE8的新手。
我有一个非常愚蠢的问题......为什么这段代码: PChar('x'); 导致“访问冲突”错误?编译器优化? 示例: var s: String; ... s := StrPas(PAnsiChar
我有一个包含一些数据的字节数组... CommandBytes : array of byte; 我有一个向蓝牙打印机发送命令的 VCL 功能。 VCL函数原型(prototype)是这个 SendD
我经常读到编译器在转换为 PChar 时会产生某种魔力。 . PChar的主要目的|是在期望零终止字符数组(C 风格的“字符串”)的库中调用外部代码。 PChar是 PWideChar 的别名类型关于
PAnsiChar 和 PChar 之间有区别吗?是什么类型? (德尔福2007年之前) 提前谢谢您! 最佳答案 D2009 及之后:是的,有。 PChar 是指向 Char 的指针,它是 unico
我正在使用delphi-xe3中的Windows API从这里实现Ping功能(http://delphi.about.com/od/internetintranet/l/aa081503a.htm)
我得到了advice from Rob Kennedy他的建议之一是使用 SetString,然后将其加载到显示它的 VCL 组件中,从而大大提高了我正在开发的应用程序的速度。 我使用的是 Delph
请考虑以下程序: program SO41175184; {$APPTYPE CONSOLE} uses SysUtils; function Int9999: PAnsiChar; begin
如何将 PAnsiChar 变量转换为 WideString 或 string? 最佳答案 您只需将一个变量分配给另一个变量,然后让 Delphi 编译器为您完成所有转换: var p: PAns
我正在将应用程序转换为 Delphi 2009,但遇到了一个有趣的问题,一些调用需要将字符串(宽)转换为 AnsiString。 这是一个演示我遇到的问题的示例: var s: PAnsiChar
情况:我有一个使用 UTF-8 作为其内部字符串格式的外部 DLL。接口(interface)函数都使用 PAnsiChar 来传递字符串。 我的应用程序的其余部分使用 Delphi 的原生 stri
所以问题是 Delphi 2009/2010 中的字符串文字(或常量字符串)是否可以直接转换为 PAnsiChar,或者是否需要先额外转换为 AnsiString 才能正常工作? 背景是我正在使用 C
作为新手,对于互操作和 C(++) 我确实搜索了这个问题的答案,但在 SO 或 www 上找不到。我没有选择正确的词来搜索答案,或者我错过了这个非常基本的问题的要点...... 对于 Delphi d
在 Delphi XE 中,我使用 BASS audio library ,其中包含此功能: function BASS_StreamCreateURL(url: PAnsiChar; offset:
我想使用 Delphi 代码,通过 C++ Builder 中的 DLL 导出 Delphi 代码片段是这样的 // function declare function NameData(ItemI
我知道这可能很简单,但有时 Unicode 问题会因为太多的考虑而困扰我。 我有这个代码: pcBuffer := StrAlloc(Stream.Size + 1) where pcBuffer i
我是一名优秀的程序员,十分优秀!