2015-02-11 58 views
-2

親愛的stackoverflowers。包含指向堆分配內存的指針的c結構的調用值

在對c和結構進行一些實驗時,我和我的一個朋友遇到了一些我們無法理解的東西。下面是一段代碼片斷,它描述了一個帶有int指針和變量的結構體。它們都是在創建主函數中的結構時設置的。

我們想知道c如何在結構上處理按值。通過引用進行調用是所有清晰,簡單的參考,所有被修改的內容都會發生變化。現在,這個奇怪的或有趣的東西來與價值的呼叫。結構被複製爲局部變量,結構中的指針和長度值也被複制。基本上創建另一個指向同一個堆內存的指針。 (糾正我,如果我錯了)。

沒有什麼,如果你釋放這個指針。這是否意味着你放棄了那裏的信息?不一定,因爲這些信息可能仍然存在於您的頁面中。但是如果你再次使用malloc的話。

爲什麼信息仍然存在?有和沒有新的malloc。這不是說操作系統給你一個新的內存塊嗎?爲什麼這個價值還在那裏?一般情況下,如果你通過一個指向堆內存的指針傳遞一個結構體的值,會發生什麼?

#include <stdio.h> 
#include <stdlib.h> 

typedef struct Struct 
{ 
    int* array; 
    int length; 
} Struct; 

void callByValue(Struct st) 
{ 
    st.array[1] = 11; 
    st.length = 11; 

    /* This is weird */ 
    free(st. array); 
} 

void callByRef(Struct *st) 
{ 
    st->array[1] = 22; 
    st->length = 22; 
} 

int main() 
{ 
    Struct s; 
    s.array = malloc(2*sizeof(int)); 
    s.array[1] = 0; 
    s.length = 0; 

    printf("Before array[1]: %d length: %d\n", s.array[1], s.length); 

    callByValue(s); 

    printf("Caal-by-value array[1]: %d length: %d\n", s.array[1], s.length); 

    callByRef(&s); 

    printf("Caal-by-reference array[1]: %d length: %d\n", s.array[1], s.length); 

    return 0; 
} 

輸出

Before array[1]: 0 length: 0 
Caal-by-value array[1]: 11 length: 0 
Caal-by-reference array[1]: 22 length: 22 
+1

嗯,你不會找到很多編譯器在堆上分配副本。堆棧是常見的選擇。無論如何,這是UB的大好時機。 – 2015-02-11 22:24:39

+0

因爲在malloc之後,在嘗試打印它之前,沒有在該指針中寫入任何內容。無論出於何種原因,malloc'ing再次沒有改變指針指向的位置。無論如何,這是UB,所以任何事情都可能發生。 – user3528438 2015-02-11 22:39:50

+0

你的假設是錯誤的。 callByValue()的st參數被複制到堆棧中。當函數返回並且堆棧指針被重置時,對st或其成員所做的任何更改都將被丟棄。 – OldProgrammer 2015-02-11 22:42:08

回答

2

在按值調用,該代碼使得結構的副本由函數使用。所以,你有這種情況

main:  s.array ---+ 
         +---> MemA (memory for 2 ints) 
callByValue: st.array ---+ 

free(st.array)後,兩個指針是無效的,因爲MemA被釋放。

malloc(1000...)後,你有這種情況

main:  s.array ---> MemA (invalid pointer) 
callByValue: st.array ---> MemB (memory for 1000 ints) 

main指針沒有更新,仍然無效。使用main中的指針將導致未定義的行爲。

+0

然而,在我們釋放後,我們可以通過引用其他函數來給結構並修改數組。首先,我們再次沒有malloc,並且確切地想到了你描述的內容。但是,我們可以訪問指針並更改堆中的數據... – Montaldo 2015-02-11 23:02:17

+0

是的,這是未定義行爲(UB)的問題。有時候你的程序似乎也能工作,即使它完全錯誤。 C語言不提供UB保護,這是您作爲程序員避免UB的義務。 [valgrind](http://valgrind.org/)可以幫助您在程序中找到UB的工具之一。我建議用valgrind運行你的代碼來查看你得到的錯誤。 – user3386109 2015-02-11 23:09:26

+0

那麼爲什麼如果我第一次malloc空間,然後釋放它,然後訪問它,操作系統不會抱怨。這僅僅是頁面問題發揮作用嗎?這可以解釋這個問題。 – Montaldo 2015-02-11 23:26:11