2011-12-07 28 views
2

我一直在狠狠地敲打着我的頭......我在main()中創建了一個指針,我將這個指針傳遞給另一個函數。在該函數內部,該指針用於創建一個新數組(使用new運算符),數組被填充,函數結束。閱讀新的填充數組給出段錯誤

如果我再嘗試訪問元素的新數組在調用者,我得到一個段錯誤。由於使用了新的操作符,我期望新的數組處於堆狀態,因此不會被超出範圍清除......我真的不明白這一點。我忽略了什麼?我也不確切地知道該怎麼做,所以沒有運氣。

我能得到它的工作,如果我讓函數返回指針(而不是通過它),但我不想這樣做,因爲最終我想我的函數來創建一些這樣的新近創建的陣列。那麼我在這裏錯過了什麼?

這裏是一個最小的工作例如:崩潰的

#include <iostream> 
#include <stdio.h> 

bool getData(double *myData) 
{ 
    myData = new double[2]; 
    if (!myData) 
     return false; 

    myData[0] = +4.53; 
    myData[1] = -3.25;  
    return true; 
} 


int main() 
{ 
    double *myData = NULL; 
    if (!getData(myData)) 
     fprintf(stderr, "Could not get data.\n"); 

    std::cout << myData[0] << std::endl; 
    std::cout << myData[1] << std::endl; 

    delete [] myData;  
} 

回答

3

根本原因:
在按值傳遞一個函數指針。指針的副本被傳遞給函數。進一步你將內存分配給通過main傳遞的指針的副本,這個指針與你在main中訪問的指針不同,它是一個副本。在主指針myData從未分配的任何內存,所以最終你解引用NULL指針,導致未定義行爲和崩潰。

建議的解決方案1:

按引用傳遞指針:

bool getData(double *&myData) 
        ^

,你是好到go.This是做它的C++的方式。

另一種解決方案:

你也可以這樣做:

bool getData(double **myData) 
        ^
{ 
    *myData = new double[2]; 
     //so on 
} 

同時調用它爲:

getData(&myData); 
     ^

一個忠告:
new不回c。中的NULL無法分配內存。它拋出了一個std::bad_alloc異常。所以你需要處理這個異常,或者如果你想檢查null,你應該使用newnothrow版本。

+0

最完整的答案。謝謝你,先生! –

0

你要通過一個雙**如myData的,正確初始化數組。目前,您的getData函數會創建一個數組並將其值存儲在複製的參數中,因此myData中的myData不會被修改。你必須通過的myData的指針,並與

bool getData(double** myData) 
{ 
    *pmyData = new double[2]; 
    ... 
} 

修改和調用的getData主:

getData(&myData); 
+0

這與傳遞指針的引用基本相同,正如其他人所建議的,只是語法上更冗長......我一直首選引用:) –

+0

我的目的是突出顯示問題,我使用指針使其更清晰。我同意你的看法,但對於初學者來說,引用並不總是容易理解的。 – neodelphi

1

指針參數的getData()是按值傳遞,而不是參考。這意味着你正在推棧棧中的值(==指針指向的地址)並調用getData。在getData內部,用new []的返回值覆蓋此值。從函數返回後,該值不再有效,因爲它只存在於堆棧中。

嘗試的引用或指針傳遞給指針:

bool getData(double *&myData) 
{ 
    myData = new double[2]; 
    if (!myData) 
     return false; 

    myData[0] = +4.53; 
    myData[1] = -3.25;  
    return true; 
} 
+0

阿當!愚蠢的我,我知道這件事很簡單。謝謝,這工作出色。 –

0

myData作爲參數getData功能上堆棧傳遞作爲拷貝給出。在修改getData函數中的值時,實際上會修改堆棧中的值。

當您返回主函數時,所有內容都與之前相同(除內存泄漏外)。

最快的解決辦法是改變getData功能是這樣的:

bool getData(double *&myData) 

和你所有的設置。

0

您將指針傳入您的函數的值,而不是引用。試試這個:

bool getData(double* &myData) 
{ 
    ... 
} 

不同的是,myData的現在是主,而不是它的副本被破壞了函數退出時,指針的引用。

+0

A)這是一個指向參考的指針,這是非法的。 B)我個人覺得指針很容易混淆,因爲他們甚至對於經驗豐富的程序員都沒有聲明像T *&p這樣的東西。只是我的觀點。 –

+0

@AssafLevy:你是對的,這是一個錯字。糾正。 –