2015-10-09 95 views
0

下面是我試圖使用的代碼。我想創建一個BankTeller對象的數組。據我的理解,當一個新的BankTeller()被調用時,它會創建一個指向該對象的指針,我將其保存到出納員中。然後,我嘗試插入到該psotion,但在使用gdb逐句通過並且程序崩潰時出現分段錯誤。創建對象數組時出現分段錯誤

BankTeller **tellers; 
BankModel(int count){ 
    srand (time(NULL)); //ignore this 
    *tellers = new BankTeller[count]; 
    for(int i=0; i <= count; i++){ 
     tellers[i] = new BankTeller(); 
    } 

    return; 
} 
+0

有沒有任何回覆完全回答你的問題?如果是這樣,請務必將其中一個標記爲已接受,以向更廣泛的社區表明您獲得了所需的內容。如果不是,那麼請務必澄清並解釋可能仍不清楚的事情。 – ray

回答

1

我認爲你的代碼比它可能需要更復雜。我會考慮使用std容器,如std::vector或更適合您的任何需求。一般來說,除非真的有必要,否則你應該避免多層次的間接尋址,在這種情況下它看起來不是這樣。

理解指針

你開始通過聲明BankTeller **tellers,這是一個指向指針BankTeller。在您的代碼中導致段錯誤的行是*tellers = new BankTeller[count];。這一行返回一個指向數組BankTeller對象的指針,但是你的雙聲道**的聲明表示它應該得到一個數組指針BankTeller對象。分配的值仍然被解釋爲一個地址(它不是),並最終嘗試訪問無效的內存位置,從而觸發段錯誤。

相反它應該是*tellers = new BankTeller*[count];。請注意開頭括號前的*。這一行將爲您提供一組指針BankTeller對象。

簡單的例子

爲了說明這一點,忘掉BankTeller S和讓我們回到原語。

#include <iostream> 
using namespace std; 

int main() 
{ 
     const size_t max = 3; 
     int **nums; 

     cout << "Creating arrays..."; 
     nums = new int*[max];    // <<---- not: nums = new int[max]; 
     for(size_t i = 0; i < max; ++i) 
       nums[i] = new int(i); 
     cout << "done" << endl; 

     cout << "Contents: "; 
     for(size_t i = 0; i < max; ++i) 
       cout << *nums[i] << ' '; // <<---- dereferenced twice to reach actual value 
     cout << endl; 

     cout << "Deleting arrays..."; 
     for(size_t i = 0; i < max; ++i) 
       delete nums[i]; 
     delete[] nums; 
     cout << "done" << endl; 
     return 0; 
} 

請注意,這與前面介紹的情況相同。要運行它,將代碼放在一個名爲test.cpp文件,並使用這個(GNU/Linux)的命令:如果你想要去在它在調試器中,加入-ggdbg++以上命令,以確保

➜ /tmp g++ test.cpp -o test && ./test 
Creating arrays...done 
Contents: 0 1 2 
Deleting arrays...done 
➜ /tmp 

您將調試符號添加到二進制文件。然後,您可以使用b <linenumber>(例如b 10)設置斷點,並使用p <variable_name>(例如p nums,p *nums等)來打印地址和值。

但是,你不需要像這樣使用原始指針。您可以也應該使用標準模板庫中的容器。

你的代碼重構

我重新寫下面的示例代碼,使用std::vector代替雙指針。

#include <iostream> 
#include <vector> 
using namespace std; 

class BankTeller 
{ 
public: 
     BankTeller() { 
       cout << "Created BankTeller\n"; 
     } 
     ~BankTeller() { 
       cout << "Destroyed BankTeller\n"; 
     } 
}; 

class BankModel 
{ 
public: 
     BankModel(size_t count) { 
       // remember to throw exception if count <= 0 
       for(size_t i = 0; i < count; ++i) 
         _tellers.push_back(new BankTeller()); 
       cout << "Created BankModel\n"; 
     } 

     ~BankModel() { 
       // consider using iterators 
       for(size_t i = 0; i < _tellers.size(); ++i) { 
         delete _tellers[i]; 
         _tellers[i] = 0; 
       } 
       _tellers.clear(); 
       cout << "Destroyed BankModel\n"; 
     } 

private: 
     vector<BankTeller*> _tellers; 
}; 

int main() { 
     BankModel *model = new BankModel(5); 
     delete model; 
     return 0; 
} 

大廈和在我的系統(GNU/Linux)的運行,它看起來如下:

➜ /tmp g++ tellers.cpp -o tellers 
➜ /tmp ./tellers 
Created BankTeller 
Created BankTeller 
Created BankTeller 
Created BankTeller 
Created BankTeller 
Created BankModel 
Destroyed BankTeller 
Destroyed BankTeller 
Destroyed BankTeller 
Destroyed BankTeller 
Destroyed BankTeller 
Destroyed BankModel 

希望這可以幫助您瞭解這兩個指針,並使用STL的好處。

0

歡迎來到C++的動態數組!正確的寫作方式是:

BankTeller* tellers = new BankTeller[count]; 

您不需要指向此指針的指針。

但是,不要這樣做!使用std::vector<BankTeller>

1

您的tellers變量是一個指向指針的指針。所以,當你做

*tellers = new BankTeller[count] 

你必須確保內存已正確分配給BankTeller*

+0

我認爲這個答案有點不準確。問題不在於內存未被「正確分配」,而是因爲錯誤的解引用會導致嘗試訪問無效的內存地址。有關更多詳細信息,請參閱[我的回覆](https://stackoverflow.com/questions/33046638/segmentation-fault-when-creating-an-array-of-objects/33047336#33047336)。 – ray

0

試試這個 -

BankTeller **tellers; 

tellers = new BankTeller* [count]; 

for(int i=0; i <= count; i++) 
     { 
      tellers[i] = new BankTeller(); 
     } 

你可以很容易地看到這裏的差別。

相關問題