2016-07-28 21 views
2

Angenommen, ich analysiere eine Umgebungsvariablenliste von einem gegebenen map<string, string> zu einem 2D-Speicher, der von unique_ptr<char*[]> gehalten wird. Ich bin mir jedoch nicht sicher, wie ich den Deleter für diesen 2D-Speicher anpassen kann.Passen Sie den Deleter an, um ein 2D-Array durch std :: unique_ptr freizugeben

// Given: env (type of map<string, string>) 
// Return: unique_ptr<char*[]> (with customized deleter) 

// Prepare for parsing the environment to c-style strings 
auto idx = size_t{0}; 

// What should I fill for `ret` a proper deleter that won't give memory leak? 
auto ret = std::make_unique<char*[]>(env.size() + 1, ???); 
for(const auto& kvp : env) { 
    auto entry = kvp.first + "=" + kvp.second; 
    ret[idx] = new char[entry.size() + 1]; 
    strncpy(ret[idx], entry.c_str(), entry.size() + 1); 
    ++idx; 
} 
ret[idx] = nullptr; // For the later use of exec call 

return ret; 

Offenbar die obige Code Lecks aufgrund der new operator in den inneren für-Schleife.

+0

Warum müssen Sie in 'unique_ptr ' konvertieren? Warum nicht 'unique_ptr ' oder sogar 'vector '? – wasthishelpful

+0

Cuz Ich brauche den zugrunde liegenden rohen Zeiger zu anderen Systemaufruf wie 'execvpe' übergeben. – Jes

Antwort

2

Es gibt keine Version von std::make_unique, die einen Deleter als Argument akzeptiert (übrigens ist std::make_unique C++ 14, nicht C++ 11). Versuchen Sie folgendes:

size_t size = env.size() + 1; 

auto ret = std::unique_ptr<char*, std::function<void(char**)> >(
    new char* [size], 
    [size](char** ptr) 
    { 
     for(size_t i(0); i < size; ++i) 
     { 
      delete[] ptr[i]; 
     } 
     delete[] ptr; 
    } 
); 

Sie ret.get() passieren können execvpe.