2012-03-19 73 views
2

我每次取消註釋l70-72時,程序都會發生運行時錯誤。這不是我第一次遇到這個特殊問題。爲什麼我有一個運行時錯誤動態內存分配(堆)?

我做一個指向對象的數組,發送指針變成一個功能,嘗試執行在主函數定義的命令,並得到一個運行時錯誤,都同時使用堆。該指針或數組中的指針會發生明顯的變化。

當我調用manage_Rectangle_arr(string strCommand, Rectangle * *arr, short *siArrayL)以下任何一種時出現錯誤:「填充數組」,「獲取區域」和「空內容」(顯然最後兩個與「填充數組」有關,因爲他們需要它首先執行以功能)

void manage_Rectangle_arr(string, Rectangle * *, short*); 

int main() 
{ 
    Rectangle * * arr; 
    short siArrayL=1; 

    manage_Rectangle_arr("make array", arr, &siArrayL); 
    manage_Rectangle_arr("fill array", arr, &siArrayL); //Problem here 
    manage_Rectangle_arr("get areas", arr, &siArrayL); //Problem here 
    manage_Rectangle_arr("empty contents", arr, &siArrayL); //Problem here 
    manage_Rectangle_arr("delete array", arr, &siArrayL); 
} 

void manage_Rectangle_arr(string strCommand, Rectangle * *arr, short *siArrayL) 
{ 
    if(strCommand=="make array") 
    arr = new Rectangle * [ *siArrayL]; 

    if(strCommand=="fill array") //Problem here 
    for(short s=0; s< *siArrayL; ++s) 
    arr[s]= new Rectangle(1, 1); 

    if(strCommand=="get areas") //Problem here 
    for(short s=0; s< *siArrayL; ++s) 
    cout << arr[s]->getArea(); 

    if(strCommand=="empty contents") //Problem here 
    for(short s=0; s< *siArrayL; ++s) 
    delete arr[s]; 

    if(strCommand=="delete array") 
    delete [] arr; 
} 

//When I call manage_Rectangle_arr(string strCommand, Rectangle * *arr, short *siArrayL) with any of the following: "fill array", "get areas" and "empty contents" (obviously the last two are related to "fill array" in nature, since they need it to be executed first in order to function) 

Full C++ Source Code

+2

如果編輯問題的最小可能代碼到問題中,則可以將此問題遷移到堆棧溢出。在目前的狀態下,我不會讓它遷移。 – ChrisF 2012-03-19 11:54:12

+3

你錯過了這一點。在問題**中包含代碼**,而不是鏈接到外部網站。 – ChrisF 2012-03-19 12:35:01

+2

我測試了你的代碼。使用Visual Studio 2010代碼崩潰只是與'刪除'取消註釋。這是因爲您嘗試刪除未分配的內存區域。 – Max 2012-03-19 12:37:37

回答

1

即使這似乎讓很多downvotes的,我會盡力提供一個有用的答案。 :)

你的陣列是Rectangle**類型的 - 也就是說,一個指向矩形的指針。你可以通過價值把它發送給一個方法。這意味着原始方法中的arr的值將被複制到manage_Rectangle_arr中的變量arr中。因此,在分配arr時,值(new內存區/數組的地址)arr將僅在被調用的函數中包含此值 - 因爲這些值完全是不同的變量。

如果改爲聲明manage_Rectangle_arr作爲

void manage_Rectangle_arr(string strCommand, Rectangle * * &arr, short *siArrayL) 

即變量/存儲區域將被引用發送,這意味着它將是另一個,自動,間接的電平。你可以通過使用一個類型爲Rectangle ***的變量和取消引用變量arr來實現這一點,但這很快就變得愚蠢。

也有許多其他的在你的代碼「不是最佳做法」,但我不會談論他們都在這裏。 :)希望這會幫助你回到正軌!

+0

嗯,我不喜歡通過引用調用,任何通過指針調用它來工作的方式? P.S .:通過引用進行調用確實有效。 – 2012-03-19 12:48:55

+0

我會嘗試三星級的方法,三星級干邑通常比雙星和單星級更好;) – 2012-03-19 12:54:19

+0

@CrawlingPastaHellion繼續,最好是如果你自己弄清楚,而不是讓我告訴你...只要你不只是隨機交換你的源代碼中的符號:)只要嘗試合併「address-of」運算符即可。提示:你不需要將它宣佈爲任何地方的三星;) – Max 2012-03-19 13:07:13

3

基本上,除了Max指出的按值調用問題外,這段代碼還有兩個錯誤。

第一個錯誤是您沒有正確使用函數,並濫用字符串以提供命令。第二個錯誤是you are using pointers。每一個C++課程都會犯這個錯誤。指針在大多數C++代碼中都沒有位置。不要陷入壞習慣。

更正和簡化,代碼應該如下所示:

int main() 
{ 
    short siArrayL=1; 
    std::vector<Rectangle> arr(siArrayL); 

    fill_array(arr); 
    print_areas(arr); 
} 

通過兩種方法:特別

void fill_array(std::vector<Rectangle>& arr) { 
    for (std::vector<Rectangle>::iterator i = arr.begin(); i != arr.end(); ++i) 
     *i = Rectangle(1, 1); 
} 

void print_areas(std::vector<Rectangle> const& arr) { 
    for (std::vector<Rectangle>::const_iterator i = arr.begin(); i != arr.end(); ++i) 
     std::cout << i->getArea(); 
} 

注意如何有沒有更多的使用了「空內容」和「刪除陣」。從不使用指針只有兩個好處。

+0

那麼,我猜我們的教師是白癡。圖也一樣。 ;)我的理念是:代碼越乾淨,代碼越好。這就是爲什麼我不喜歡基於LISP的語言(很難閱讀)。 謝謝,我會詳細研究你的答案,Konrad。現在我的頭因各種指針而受傷。 :( – 2012-03-19 13:38:16

+0

@CrawlingPastaHellion這是你的教授想法的'字符串查找'嗎? – Max 2012-03-19 16:24:43

+0

是公平的,有時一個輔導練習可能是人爲的,因爲輔導教師試圖讓你理解這個問題,它不是「現實世界」的代碼解決方案*如果*這是爲了強制理解指針,那麼這個答案會得到一個F.(即使我把它寫成我的工作中的答案) – gbjbaanb 2012-03-19 17:46:31

相關問題