简体   繁体   中英

Seg fault unique_ptr with factory design attempt

I'm getting a segmentation fault when trying to use a unique_ptr to create instances of derived classes. Before, I had coded every instantiation of the seven derived classes, one after the other and the code was working properly.

Current code is the following:

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

Do you see any reason for this to seg fault?

function createInstance has the chance to return nullptr , you need to check the pointer is valid:

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

This line is the error:

ComumPtr ptr;       // initialized to nullptr.

While I understand that nullity is so easy , it's also the best way to shoot yourself in the foot (whether in C++ or Java), because now any single use of the result of this function need be checked.

Instead, you could:

  • use a Null object: the method readDatabaseFields will just do nothing
  • choose to throw an exception rather than returning a null pointer

None of the above alternative is inherently better than the other, it very much depends on the situation; however both are better than returning a null unique_ptr .

Supposing you'd elect the exception method:

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");
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM