从字节数组创建字符串 [英] Creating string from byte array

查看:234
本文介绍了从字节数组创建字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用以下代码中的 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/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.

这篇关于从字节数组创建字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆