DELPHI之關於String的記憶體分配 引

2022-07-24 11:54:11 字數 3649 閱讀 7122

在函式、過程或者方法中定義乙個字串變數時,由於我們知道在函式、過程或者方法中定義的變數為區域性變數,它的記憶體

是在棧中分配的,但是這裡有個小細節我們要注意,對於乙個區域性的字串變數,它的大小為4位元組,這個在棧中分配的4字

節是不是就是字串變數的全部呢?答案是否定的,它在棧中儲存的只是這個字元變數的大小和字元變數的值在堆中的記憶體

位址!,這就是說,該字元變數的值並不在對應的棧中,而是在堆中!我們了解到在堆上分配的記憶體是要程式設計師來處理記憶體

釋放的,而我們在使用string型別的變數時從來就沒有處理過該變數占用的記憶體!這是什麼原因呢?這裡我們就要講到

編譯器的引用計數原理了,正是因為它為我們省去了很多麻煩(當然,在某些情況我們還是小心為上,下面會提出),引用

計數其實通俗的講就是這塊記憶體被幾個變數引用,就為這塊記憶體計上數(可能表述不正確,但為了好記好理解故此說),是

1個就是1,有2個就是2,以此類推。當乙個字串變數使用完後,編譯器自動的將其引用計數減1,如果發現引用計數為0

時,這個字元變數所占用的記憶體空間就被釋放了。需要注意的是,什麼情況下會發生引用計數呢?如果定義乙個字串變數

並給其賦值,那麼這個字串變數引用計數為1,此時假若我們再定義乙個字串變數,並將第乙個字元變數的值賦值給第

二個字元變數,此時將引發引用計數,變為2,注意,編輯器此時並沒有給第二個字元變數複製乙份第乙個字元變數的值,

而只是將第乙個字元變數值的位址指標給了它!也就是說,第乙個和第二個字元的值都在同乙個記憶體塊中!。但是我們通過

訪問陣列元素的方式訪問字元變數的時候或者修改上面其中乙個字元變數時,這時會引發」寫複製「,之後兩個字串變數開

始使用不同的記憶體占用。因為所有這些對程式設計師來說是不必費心處理的,它全部由編譯器來自動完成,那麼我們在什麼情況

下要小心呢?這裡就和dll有關係了,我們知道在exe程式呼叫dll時,exe和dll之間都是各自使用自己的記憶體管理器,

麻煩就出在這,假如我們在exe中呼叫dll的乙個輸入函式時返回乙個字串,我們知道這個字串的引用計數為1,exe在

使用完這個字串後將其引用計數減1,那就是0了,按照慣例,編譯器對字串所占用的記憶體進行清除釋放,ok,一切順利,

那麼這時該輪到dll處理了,前面說過exe和dll各有各的記憶體管理器,這時dll是不知道exe已將字串記憶體釋放掉了,並

且還要訪問那個被釋放了的字串,字串都不存在了,訪問哪兒呢?於是程式就出問題了,很顯然這是我們所不希望看到的,

所在在使用dll時,為了避免這個問題發生,我們可以有多種解決方案

1、使用記憶體對映檔案

2、dll單元和exe單元都引用sharemem單元

3、不用string型別(注:動態陣列、介面和變體型別也有引用計數機制),改用pchar型別

在函式、過程或者方法中定義乙個字串變數時,由於我們知道在函式、過程或者方法中定義的變數為區域性變數,它的記憶體

是在棧中分配的,但是這裡有個小細節我們要注意,對於乙個區域性的字串變數,它的大小為4位元組,這個在棧中分配的4字

節是不是就是字串變數的全部呢?答案是否定的,它在棧中儲存的只是這個字元變數的大小和字元變數的值在堆中的記憶體

位址!,這就是說,該字元變數的值並不在對應的棧中,而是在堆中!我們了解到在堆上分配的記憶體是要程式設計師來處理記憶體

釋放的,而我們在使用string型別的變數時從來就沒有處理過該變數占用的記憶體!這是什麼原因呢?這裡我們就要講到

編譯器的引用計數原理了,正是因為它為我們省去了很多麻煩(當然,在某些情況我們還是小心為上,下面會提出),引用

計數其實通俗的講就是這塊記憶體被幾個變數引用,就為這塊記憶體計上數(可能表述不正確,但為了好記好理解故此說),是

1個就是1,有2個就是2,以此類推。當乙個字串變數使用完後,編譯器自動的將其引用計數減1,如果發現引用計數為0

時,這個字元變數所占用的記憶體空間就被釋放了。需要注意的是,什麼情況下會發生引用計數呢?如果定義乙個字串變數

並給其賦值,那麼這個字串變數引用計數為1,此時假若我們再定義乙個字串變數,並將第乙個字元變數的值賦值給第

二個字元變數,此時將引發引用計數,變為2,注意,編輯器此時並沒有給第二個字元變數複製乙份第乙個字元變數的值,

而只是將第乙個字元變數值的位址指標給了它!也就是說,第乙個和第二個字元的值都在同乙個記憶體塊中!。但是我們通過

訪問陣列元素的方式訪問字元變數的時候或者修改上面其中乙個字元變數時,這時會引發」寫複製「,之後兩個字串變數開

始使用不同的記憶體占用。因為所有這些對程式設計師來說是不必費心處理的,它全部由編譯器來自動完成,那麼我們在什麼情況

下要小心呢?這裡就和dll有關係了,我們知道在exe程式呼叫dll時,exe和dll之間都是各自使用自己的記憶體管理器,

麻煩就出在這,假如我們在exe中呼叫dll的乙個輸入函式時返回乙個字串,我們知道這個字串的引用計數為1,exe在

使用完這個字串後將其引用計數減1,那就是0了,按照慣例,編譯器對字串所占用的記憶體進行清除釋放,ok,一切順利,

那麼這時該輪到dll處理了,前面說過exe和dll各有各的記憶體管理器,這時dll是不知道exe已將字串記憶體釋放掉了,並

且還要訪問那個被釋放了的字串,字串都不存在了,訪問哪兒呢?於是程式就出問題了,很顯然這是我們所不希望看到的,

所在在使用dll時,為了避免這個問題發生,我們可以有多種解決方案

1、使用記憶體對映檔案

2、dll單元和exe單元都引用sharemem單元

3、不用string型別(注:動態陣列、介面和變體型別也有引用計數機制),改用pchar型別

DELPHI之關於String的記憶體分配

函式 過程或者方法中定義乙個字串變數時,由於我們知道在函式 過程或者方法中定義的變數為區域性變數,它的記憶體是在棧中分配的,但是這裡有個小細節我們要注意,對於乙個區域性的字串變數,它的大小為4位元組,這個在棧中分配的4字節是不是就是字串變數的全部呢?答案是否定的,它在棧中儲存的只是這個字元變數的大小...

關於delphi指標

大家都認為,c語言之所以強大,以及其自由性,很大部分體現在其靈活的指標運用上。因此,說指標是c語言的靈魂,一點都不為過。同時,這種說法也讓 很多人 產生誤解,似乎只有c語言的指標才能算指標。basic不支援指標,在此不論。其實,pascal語言本身也是支援指標的。從最初的pascal發展至今 的ob...

delphi中dll返回string問題

有高手言 1.在dll中定義返回string字串的函式時,如果沒有特殊處理呼叫該函式 在退出呼叫該函式的過程 函式 事件 時,會出現以下錯誤 invalid pointer operator 2.當在單元中新增sharemem時,在退出程式的時候會出現同樣的錯誤 3.當在呼叫dll的專案檔案中 不是...