Delphi 字串的引用計數與生命週期

2022-04-01 13:18:18 字數 2945 閱讀 2087

先來段**

type

mystring = ansistring;

pmychar = pansichar;

procedure tform2.button2click(sender: tobject);

varp: pmychar;

s, s2: mystring;

begin

self.caption := '

frmtest

';  //7位的字串

p := getcaption;

s2 := p;   //這是時候s2 為frmtes

showmessage(s2);  //*****顯示出來為frmtes

end;

function tform2.getcaption: pmychar;

vars1, s2: mystring;

begin

s2 := mystring(self.caption);

result := pmychar(mystring(s2));

end;

研究說明(代表個人意見)(xe下面測試)

function tform2.getcaption: pmychar;

vars1: mystring;

begin

s1 := mystring(self.caption);    原始碼得知,是獲取了一塊臨時的空間(a1)

//a1(integer(s1))

i:= stringrefcount(s1);  //i=1

result := pmychar(mystring(s1));  //result指標指向的為(a1)的空間

//integer(@result^) = a1(integer(s1))  是指向同一塊空間

i:= stringrefcount(s1);  //i=1

end;

//函式返回後s1因為是區域性變數 s1的引用計數為0,integer(s1)的空間被標誌為可以覆蓋

//返回的為指標,不增加s1的引用計數

procedure tform2.button2click(sender: tobject);

varp: pmychar;

s, s2: mystring;

begin

self.caption := '

frmtest

';p := getcaption; //實際上p指向的那塊位址被標註為可以覆蓋,隨時都有可能被覆蓋,是很危險的

//integer(@p^) = getcaption內部給s1分配的那塊空間位址

s2 := p;         //導致丟掉了字元..

//因為p指向的記憶體是可以被覆蓋的,s2分配的位址可能和p指向的位址是一樣的,導致丟掉了字元..

//integer(s2) 可能= integer(@p^)  測試是發現都一樣

//下面操作(setlength)同樣也會一樣結果,s2占用的和p占用的同樣大小(或者小)。

//這樣導致了s2分配的空間可能和p記憶體一樣

//如果7改成較大的數就正常

//  setlength(s2, 7);

//  strcopy(pmychar(s2), p);

showmessage(s2);  //錯誤

end;

解決方案(1)

將s1定義為內成員變數,這樣當getcaption執行完後那塊空間不會被標準為可讀寫

function tform2.getcaption2: pmychar;

begin

fmycaption := mystring(self.caption);    原始碼得知,是獲取了一塊臨時的空間(a1)

//a1(integer(fmycaption))

i:= stringrefcount(fmycaption);  //i=1

result := pmychar(mystring(fmycaption));  //result指標指向的為(a1)的空間

//integer(@result^) = a1(integer(fmycaption))  是指向同一塊空間

i:= stringrefcount(fmycaption);  //i=1

end;

//執行完後fmycaption不是臨時變數,指向的位址不可以被覆蓋

procedure tform2.btngetcaption2click(sender: tobject);

varp: pmychar;

s, s2: mystring;

begin

self.caption := '

frmtest

';p := getcaption2; //實際上p指向的那塊位址和fmycaption的位址是一樣的

//integer(@p^) = getcaption2內部給fmycaption分配的那塊空間位址是一樣

s2 := p;

//因為p指向的記憶體是不可以被覆蓋的,s2分配的位址不可可能和p指向的位址是一樣的,這樣做是安全的

//integer(s2) <> integer(@p^)

i:= stringrefcount(s2);  //i=1  新的記憶體

showmessage(s2);  //正確

end;

區域性變數

function tform2.getcaption2: pmychar;

vars1: mystring;

begin

s1 := '

frmtest

'i:= stringrefcount(s1);  //i=-1  常量位址指向空間不可被覆蓋

//uniquestring(s1); 

//i:= stringrefcount(s1);  //i=1  s1又變成臨時的,函式返回後s1指向的位址不再安全

result=pmychar(s1)

end;

引用計數與智慧型指標

c 沒有完善的gc機制,直到c 11才在stl中正式引入了智慧型指標。出現在庫中說明智慧型指標不是語言特性。c 智慧型指標實現了部分自動記憶體管理的目的。引用計數是使用資源管理函式 構造析構複製等函式 和作用域原理實現的。每塊動態分配的記憶體 堆記憶體 都維護乙個相應的計數器,來記錄指向該記憶體的變...

Python中的引用計數

為了跟蹤記錄已經分配的記憶體,python 做法類似於撲克牌遊戲中的記牌手法。乙個物件在建立時被加上乙個引用。乙個內部的引用記錄變數將跟蹤記錄下每個物件有多少個引用。乙個物件被建立和被賦值時,它的初始引用計數為 1。物件新的引用也叫別名 alias 發生在 其他變數也被賦值到同乙個物件 物件作為呼叫...

引用計數器 與 記憶體管理

一 引用計數器的基本操作 1.方法的基本使用 1 retain 計數器 1,會返回物件本身 2 release 計數器 1,沒有返回值 3 retaincount 獲取當前的計數器的值 4 dealloc 當乙個person物件被 的時候,就會自動呼叫這個方法 void dealloc 2.概念 1...