从字节数组创建字符串
我正在尝试使用以下代码中的 StringOf
函数创建字符串。为什么在用于创建字符串 Showmessage
的数组的 ZeroMemory
之后不显示任何内容。为什么?在带有注释的 ZeroMemory
情况下,显示 =====
。
I'm trying to create string using StringOf
function in code below. Why after ZeroMemory
on array that was used to create string Showmessage
displays nothing. Why? In commented ZeroMemory
case =====
is displayed.
TIdBytes = array of Byte;
procedure fill(var b: TIDBytes);
begin
setlength(b,5);
b[0]:=61;
b[1]:=61;
b[2]:=61;
b[3]:=61;
b[4]:=61;
end;
procedure TMainForm.FormCreate(Sender: TObject);
var
POSSaleTransaction: TPOSSaleTransaction;
s: ansistring ;
b:TIDBytes;
begin
fill(b);
s := StringOf( TArray<byte>(b) );
ZeroMemory(@b, Length(b));
Showmessage(s);
end;
我正在使用Delphi XE4
I'm using Delphi XE4
我尝试使用ZeroMemory的原因是,我不会100%保证新创建的字符串不使用对byte []的引用,而是复制b数据。借助于ZeroMemory,我希望删除 b
的内容,同时希望它不会影响字符串。
The reason I'm trying to ZeroMemory is that I wont to be 100% shure that newly created string is not using reference to byte[], but copyes b data. With help of ZeroMemory I'm deleting contents of b
while expecting that it will not have influence on string.
您只需在此处清除堆栈变量即可。 B
指针(全部)和部分指针 S
((Length( b)-SizeOf(b))
个字节)。
You just blew the stack variables there. Both the B
pointer (in its entirety) and partially the pointer S
( (Length(b) - SizeOf(b))
bytes of it ).
什么是 b
?它是一个复杂的结构,一个句柄,一个指针。通常,您不想破坏内存结构,而是希望将数据放入单元中。但是在您的示例中,您只是擦除了分配在堆栈上的整个内存结构。
What is b
? it is a some complex structure, a handle, a pointer. Usually You do not want to destroy memory structure, you want to put the data into the cells. But in your example you just wiped out the whole memory structures allocated on stack. Including, probably, the string itself.
下面的程序在Delphi XE2中按预期方式工作-看看那里有什么,而不是零内存。当您想使用低级技巧作为原始指针(或诸如 ZeroMemory
的无类型变量)时,请阅读Delphi中的动态数组以及从CPU汇编程序的角度来看如何分配它们。 )
The following program works as expected in Delphi XE2 - see what is there instead of Zero Memory. Read what are dynamic arrays in Delphi and how they are allocated from CPU Assembler point of view when you want to use low-level tricks as raw pointers ( or untyped variables like in ZeroMemory
)
program Project11;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils;
procedure fill(var b: TBytes);
begin
SetLength(b,5);
// b[0]:=61; b[1]:=61; b[2]:=61; b[3]:=61; b[4]:=61;
FillChar(b[Low(b)], Length(b), 61); // Less copy-paste, more program structure
// Notice, above i take pointer to the cell inside the array,
// not to the array the container itself.
// That is both safer and does document the intention of the code
end;
Procedure SOTest();
var
s: ansistring ;
b: TBytes;
begin
fill(b);
s := StringOf( b );
// ZeroMemory(@b, Length(b)); -- destroying the pointer instead of freeing memory - is a memory leak
// FillChar(b, Length(b), 0); -- same as above, written in Pascal style, rather than C style.
b := nil; // this really does free the DYNAMIC ARRAYS. Laconic but prone to errors if mistyped.
// SetLength(b, 0); -- more conventional and safe method to do the same: free string or dyn-array.
// Anyway that is unnecessary - both b and s would anyway be auto-freed before the function exit.
Writeln(Length(s):4, ' ', s);
end;
begin
try
{ TODO -oUser -cConsole Main : Insert code here }
SOTest;
Write('Press Enter to exit;'); ReadLn;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
请参见手册。
- http://docwiki.embarcadero.com/Libraries/XE4/en /System.FillChar
- http://docwiki.embarcadero.com/RADStudio/XE4/en/Parameters_(Delphi)#Untyped_Parameters
- http://docwiki.embarcadero.com/RADStudio/XE4/en/Structured_Types#Dynamic_Arrays
- http://docwiki.embarcadero.com/Libraries/ XE4 / en / System.SysUtils.TBytes
- http://docwiki.embarcadero.com/Libraries/XE4/en/Sy stem.SysUtils.StringOf
- http://docwiki.embarcadero.com/Libraries/XE4/en/System.FillChar
- http://docwiki.embarcadero.com/RADStudio/XE4/en/Parameters_(Delphi)#Untyped_Parameters
- http://docwiki.embarcadero.com/RADStudio/XE4/en/Structured_Types#Dynamic_Arrays
- http://docwiki.embarcadero.com/Libraries/XE4/en/System.SysUtils.TBytes
- http://docwiki.embarcadero.com/Libraries/XE4/en/System.SysUtils.StringOf
所以下一个问题是为什么您要调用ZeroMemory,这有什么意义?是否有soem企图破坏密码密钥或其他敏感数据? http://www.catb.org/~esr/faqs/smart -questions.html#goal
So the next question is WHY were you trying to call ZeroMemory, what is the point there ? IS there soem attempt to destroy a cypher key or other sensitive data ? http://www.catb.org/~esr/faqs/smart-questions.html#goal
如果您只想确保 s变量没有任何外部引用-则有一个特殊功能, UniqueString
。
If you only want to assure that "s" variable does not have any external references - there is a special function for it, UniqueString
.
- http://docwiki.embarcadero.com/Libraries/XE4/en/System.UniqueString
但是在这种特定的工作流程和特定的Delphi版本中,无论如何都不会发生。再次阅读 StringOf
的手册-它返回 UnicodeString
临时隐藏变量。该变量在XE4中的 UTF-16
中进行编码,这意味着每个字母具有2个字节,这意味着原始字节链无论如何都不适合并将其转换为新的缓冲区。
However in this particular workflow and this particular Delphi version that could not happen anyway. Read again manual for StringOf
- it returns a UnicodeString
temporary hidden variable. That variable is encoded in UTF-16
in XE4, which means having 2 bytes per letter, which means the original byte-chain would not suit anyway and would be transformed into new buffer.
之后,将 UnicodeString
临时隐藏变量转换为 AnsiString
变量 s
每个字母具有一个字节,因此它也不能引用temp-var,但会分配另一个独立的缓冲区来保存转换后的数据。
After that you convert the UnicodeString
temporary hidden variable into AnsiString
variable s
having one byte per letter, so it also can not have references to the temp-var, but would allocate yet another independent buffer to hold the transformed data.
如您所见,有两个必需的复制转换操作,这两个操作都使得保持数据引用变得不可能。
As you can see there is two necessary copy-with-transformation operations, both of which make keeping data references just impossible.