2013-01-21 78 views
0

聲明:我對C非常陌生。我試圖找到這個答案,但是我的google-fu失敗了,因爲我不完全知道我應該用於搜索...新變量指向舊變量

目前,我有一個相當意想不到的問題,其中代碼int a = 100;在一個結構中也使一個整數也改變值。

從調試器中,我可以看到a和s-> pos指向相同的值。這是我的代碼的清理版本。

typedef struct { 
    char data[4096]; 
    int start; 
    int end; 
} buffer; 

typedef struct { 
    int * data; 
    int length; 
} data_format; 

buffer * create_buffer() { 
    buffer result; 
    result.start = -1; 
    return &result; 
} 

data_format * method(buffer * s) { 
    data_format result = (data_format) { malloc(100), 0 }; 
    ... // POINT1 
    int a = 100; 
    ... // POINT2 
} 

int main(int argc, char **argv) { 
    buffer * s = create_buffer(); 
    data_format * df = method(s); 
} 

從調試器,我可以看到,在標有// POINT1行,a是-1;在// POINT2,既as->start現在100

不應該int聲明建立在內存現貨尚未使用的任何一個變量?

+0

我懷疑在你沒有顯示的函數中,你正在以'result'類似的方式分配你的緩衝's',然後做'return&s'或類似的東西,因爲看起來你將會如何從顯示的功能返回結果。那是對的嗎? – iagreen

+0

是的,s可能指向方法堆棧的開始,malloc,0和100與buffer.data,start和end重疊。雖然不能確定發佈的代碼是否不完整。它甚至沒有編譯。 – aib

+0

@iagreen我剛剛編輯了這個問題。如你所說,我確實創造了一些東西。但我沒有看到'a'可以被分配與's-> start'相同的內存點。我的代碼很雜亂,充滿了其他東西。然而,我的編輯應該使代碼現在可編譯... – jdferreira

回答

4

你違反了局部變量的範圍,返回它的地址create_buffer

在堆棧上創建局部變量,並且在每次函數調用時重用堆棧。通過返回create_buffer中的result的地址,您將保存C僅在create_buffer函數期間保留供您使用的一段內存地址。當它終止時,該內存被重用。在這種情況下,當您撥打method時,它是否與s變量保持一致。你需要動態地分配你的返回變量malloc

根據你的編譯器,你應該從它得到關於返回一個局部變量的地址的警告。

+0

謝謝! 現在我改變了'buffer result = malloc(sizeof(buffer))'。我應該讓ceate_buffer返回一個真正的緩衝區而不是指針嗎? – jdferreira

+0

不,仍返回指針,將您的聲明更改爲指針 - 「buffer * result = malloc(sizeof(buffer))'。你也必須對你的'data_format結果'做同樣的事情,你將不得不逐個初始化你的結構元素,因爲我認爲'{}'初始化器不能在動態分配的對象上工作。 – iagreen

+0

非常感謝!我接受了這個答案:) – jdferreira

2

請原諒我的無知,但在C,有點像create_buffer甚至可能嗎?您在堆棧上創建result,然後返回指向它的指針。執行create_bufferresult是否會被破壞?所以現在s指向'垃圾'。也許像aib在評論中說的那樣,它指向的內存地址恰好是a的地址。

相反,create_buffer也應該mallocbuffer,那麼你可以安全地返回一個指針。

+0

你可以做到 - 看問題中的代碼 - 但它會導致_undefined behaviour_這意味着任何事情都可能發生,你不能抱怨。變量'result'超出範圍,這意味着它的內存可以重用於其他目的。它可能沒有被正式銷燬(沒有在它上面寫入空白或類似的東西),但它的價值是完全不可靠的。 –

+2

你不是無知的;你*尊重*。這是C,所以完全「有可能」跑到la-la-undefined-行爲的土地上,相信一切都很好,但實際上並非如此(例如OP的帖子)。你是正確的,必須使用一些有生命週期*外的函數(可能是一個malloc,一個全局的等等)。不是本地範圍的緩衝區地址。 – WhozCraig

+0

@JonathanLeffler我很清楚,我承認我的言辭很差。雖然我不知道它的細節不一定被破壞。這是我在C++中的理解。我想在C中應用不同的規則,或者我的理解完全不正確。感謝提醒我:) WhozCraig謝謝:) –