2013-10-22 91 views
4

我想了解如何指向字符串工作的指針。我有一個代碼(不完全是原創的),這是由某人編寫的,而且這個人不在這裏了,所以我需要理解這種用法​​的想法。使用字符串指針通過Windows消息發送一個字符串

var 
    STR: string; 
    pStr: ^string; 
begin 
    STR := 'Hello world'; 
    New(pStr); 
    pStr^ := STR; 

    PostMessage(Handle, WM_USER+1, wParam(pStr), 0); 
end; 

現在我肯定知道,一個消息處理程序獲取消息和指針包含字符串,它可以與工作,但這些操作的「引擎蓋下」發生了什麼?

我試圖做一個小項目。我認爲,將字符串分配給str指針指向的內容實際上會增加原始字符串的refcount,並且不會創建任何字符串的副本,但refcount保持爲1,並且似乎它複製了內容。

所以得到問題,發生了什麼?在指針上調用New會分配一個空字符串,對吧? 分配後,我試着看看refcount /字符串的長度指針指向這樣的PChar(@pStr^[1])[-8],但它返回廢話(14),並且長度字節也是錯誤的。

此外,問題是,使用指針以這種方式傳遞字符串通過Windows消息傳遞是否安全?

+2

這樣的數據傳輸是安全的。但也有風險,因爲如果收件人未收到您要發佈的郵件,或者如果該收件人由於某種原因未釋放分配的內存,則會發生泄漏。 – TLama

+1

使用WM_COPYDATA,您可以將任何數據發送給任何收件人。無需創建其他解決方案。 – Alexandr

+0

@TLama,接收者不會收到消息的情況是什麼? –

回答

8

New(pStr)在堆上分配一個string並返回一個指向它的指針。因爲string是一個託管類型,所以字符串默認初始化爲空字符串。由於string是作爲一個指針實現的,所以你基本上有一個指向指針的指針。

你的代碼非常好,只要你只發布消息到你自己的進程。由於消息的有效負載是一個指針,因此它僅僅意味着在進程的虛擬地址空間的上下文中。如果你想發送到不同的進程,你需要一個IPC機制。

顯然,在將消息從隊列中拉出的代碼中,您需要處理該字符串。類似這樣的:

var 
    p: ^string; 
    str: string; 
.... 
p := Pointer(wParam); 
str := p^; 
Dispose(p); 

您的代碼查詢引用計數和長度是錯誤的。以下是如何正確地做到這一點:

{$APPTYPE CONSOLE} 

var 
    pStr: ^string; 
    p: PInteger; 

begin 
    New(pStr); 
    pStr^ := 'Hello world'; 

    p := PInteger(pStr^); 
    dec(p); 
    Writeln(p^); // length 
    dec(p); 
    Writeln(p^); // ref count 

    Readln; 
end. 

輸出:

 
11 
1 
+0

備註:不應該是'str:= string(p ^);'('^'added)? – ALZ

+0

@alz str:= p ^;就足夠了 –