2013-01-06 35 views
0

我得到一個segmentation fault試圖用unique_ptr創建派生類的實例時。 之前,我曾編碼的七個子類的實例每次,一前一後的代碼工作正常。賽格故障的unique_ptr與工廠設計嘗試

當前的代碼如下:

typedef std::unique_ptr<Comum> ComumPtr; 

ComumPtr createInstance (string dom, map<string, string> & config, map<string, string> & config_fields) 
{ 
    ComumPtr ptr;  // initialized to nullptr. 
    if (dom == "voice") { 
    ptr.reset (new Voice (config, config_fields)); 
    // } else if (dom == "account") {  // FOR OTHER DERIVED CLASSES 
    // ptr.reset (new Account (config, config_fields)); 
    } 
    return ptr; 
} 

// At main function: 
for (vector<string>::const_iterator cit = for_domain.begin(); cit != for_domain.end(); ++cit) { 
    const char * section (cit->c_str()); 
    string fsn = *cit + "_fields"; 
    const char * fields_section_name (fsn.c_str()); 
    const char * db_section ("Database"); 

    map <string, string> domain_config = cfg.getSectionConfig (config_file.c_str(), section); 
    map <string, string> domain_config_fields = cfg.getSectionConfig (config_file.c_str(), fields_section_name); 
    map <string, string> database_config = cfg.getSectionConfig (config_file.c_str(), db_section); 

    std::unique_ptr<Comum> domain = createInstance(*cit, domain_config, domain_config_fields); 

    domain->readDatabaseFields (database_config); // <- segmentation fault 

你看不到任何原因賽格故障?

回答

1

function createInstance必須返回nullptr,則需要檢查指針是有效的機會:

if (domain.get()) 
{ 
    domain->readDatabaseFields (database_config); 
} 
+0

事實上,它指向NULL。忘記包括該支票。在createInstance中,在'main'中修改''dom =='voice''應該有'voice'大寫。謝謝。 – Luis

1

此行是錯誤:

ComumPtr ptr;  // initialized to nullptr. 

雖然我明白,無效是那麼容易,它也是搬起石頭砸自己的腳(無論是在C++或Java)的最佳方式,因爲現在任何一個使用這個函數的結果需要進行檢查。

相反,你可以:

  • 使用空對象,方法readDatabaseFields會坐視不管
  • 選擇拋出一個異常,而不是返回一個空指針的

無以上替代方案本質上比另一方更好,這很大程度上取決於情況;然而,兩者都比返回null unique_ptr好。

假如你選擇的例外方法:

ComumPtr createInstance (string dom, map<string, string> & config, map<string, string> & config_fields) 
{ 
    if (dom == "voice") { 
     return ComumPtr (new Voice (config, config_fields)); 
    } 
    if (dom == "account") { 
     return ComumPtr (new Account (config, config_fields)); 
    } 

    throw std::runtime_error("Unknown config field"); 
}