У меня есть класс с одной статической функцией. Целью является предоставление общего интерфейса для приложения для извлечения объекта журнала, который будет регистрироваться в определенном файле (предполагая, что пока файл не может быть представлен различными файловыми обозначениями). Каждый объект журнала хранится на карте с соответствующим именем файла. Вместо создания нового регистратора, если же имя файла снова передается в config
объекта, старый регистратор возвращается:C++ unique_ptr вызывает приложение для сбоя
typedef std::unique_ptr<AbstractLogger> LoggerPtr_t;
typedef std::map<std::string, LoggerPtr_t >::iterator LoggerMapIt_t;
std::map<std::string, LoggerPtr_t> LoggerFactory::mLoggerMap;
LoggerPtr_t LoggerFactory::getGenericLogger(const LoggerConfig& config){
std::string filename = config.getFileName();
LoggerMapIt_t itLogger = mLoggerMap.find(filename);
if(itLogger == mLoggerMap.end()){
mLoggerMap.insert(std::make_pair(filename, LoggerPtr_t(new SimpleLogger(config))));
itLogger = mLoggerMap.find(filename);
}
//if i uncommend the following 4 lines everything works fine
if(itLogger != mLoggerMap.end()){
return std::move(itLogger->second);
}
else
return LoggerPtr_t(new SimpleLogger(config));
}
Но, похоже, что сбой приложения, если различные потоки пытаются записать на тот же регистратор. Файл (означает std::ofstream
) защищен мьютексом в методе log
от SimpleLogger
. Я думаю, что причиной этого является unique_ptr
. Во всяком случае, я хотел бы иметь только один указатель на объект журнала, потому что эти объекты ведут себя как уникальный элемент (для каждого файла только один регистратор).
Возможно ли, что сбой приложения вызван unique_ptr
? Я использую unique_ptr
неправильно? Есть ли лучшее решение для достижения моих намерений?
EDIT: У меня есть много хороших ответов на эти вопросы. Наконец, я адаптировал решение Jarod в своем кодексе, но ответ Джо также очень полезен.
Когда getGenericLogger() вызывается с новым именем файла, вы создаете новый объект SimpleLogger() и добавляете его на карту, а затем снова создаете новый и возвращаете это. Вероятно, вы захотите вернуть первый в этом случае, а не создать еще один. – jksoegaard
Создаю новый объект Logger, добавьте его на карту, найдите регистратор на карте и верните его с помощью move (itLogger-> second) .... по крайней мере, это то, что я намеревался. –
Вы хотите передать право собственности на свой метод? – Jarod42