C++unique_ptr导致应用程序崩溃
C++ unique_ptr causes Application to crash
我得到了一个带有一个静态函数的类。其目的是为应用程序提供一个通用接口,以检索将记录到特定文件的记录器对象(目前假设一个文件不能用不同的文件路径符号表示)。每个记录器对象都存储在一个带有相应文件名的映射中。如果在config
对象中再次传递相同的文件名,则不会创建新的记录器,而是返回旧的记录器:
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
)由SimpleLogger
的log
方法中的互斥对象保护。我想unique_ptr
是原因。无论如何,我希望只有一个指向记录器对象的指针,因为这些对象的行为就像一个唯一的元素(对于每个文件只有一个记录器)。
应用程序崩溃是否可能是由unique_ptr
引起的?我用错unique_ptr
了吗?有更好的解决方案来实现我的意图吗?
编辑:我对这些问题有很多很好的回答。最后,我在代码中修改了Jarod的解决方案,但Joe的回答也很有用。
此行将从std::map
"获取"unique_ptr
if(itLogger != mLoggerMap.end()){
return std::move(itLogger->second);
}
因此,itLogger
刚刚指向的mLoggerMap
中的unique_ptr
现在是nullptr
。如果稍后指向该元素,或者从另一个线程返回,则尝试对该unique_ptr
执行任何操作都会导致问题,因为您在前面std::move
是指针。
如果不想放弃指针的所有权,而是只想访问指针,您也可以更改函数的签名以返回底层的原始指针
AbstractLogger* LoggerFactory::getGenericLogger(const LoggerConfig& config)
然后你可以说
if(itLogger != mLoggerMap.end()){
return itLogger->second.get();
}
否则,如果确实希望将所有权放弃/转移给调用者,则可能需要从映射中删除该元素,然后返回移动的指针。
当前,您转移所有权,因此映射包含空的unique_ptr
。所以第二个调用检索空的unique_ptr
。
因为看起来你不想所有权转移,我会写下面的代码:
AbstractLogger& LoggerFactory::getGenericLogger(const LoggerConfig& config)
{
const std::string& filename = config.getFileName();
auto& logger = mLoggerMap[filename]; // insert (default) empty unique_ptr if not present.
if (logger == nullptr) {
logger = std::make_unique<SimpleLogger>(config);
}
return *logger;
}
这显示了如何使用std::shared_ptr
(草稿,未测试):
using LoggerPtr_t = std::shared_ptr<AbstractLogger>;
using LoggerMapIt_t = std::map<std::string, LoggerPtr_t>::iterator;
std::map<std::string, LoggerPtr_t> LoggerFactory::mLoggerMap;
LoggerPtr_t LoggerFactory::getGenericLogger(const LoggerConfig& config) {
// TODO: need to protect this whole method by a mutex
std::string filename = config.getFileName();
LoggerMapIt_t itLogger = mLoggerMap.find(filename);
if (itLogger == mLoggerMap.end()) {
LoggerPtr_t ptr(new SimpleLogger(config));
mLoggerMap.insert(std::make_pair(filename, ptr));
return ptr;
} else {
return itLogger->second;
}
}
但你真的应该完全检查Jarod42的答案。关键是,您必须决定记录器对象的所有权。
使用std::unique_ptr
和引用(如Jarod42的回答中所示)是更有效的代码,因为std::shared_ptr
(甚至意味着"共享所有权")比std::unique_ptr
更昂贵。
但另一方面,由于您的全局LoggerFactory::mLoggerMap
实例,您必须注意静态初始化和去初始化。
您可以通过使用例如singleton模式getter函数来解决这个问题(假设您甚至可以从其他全局实例c'tors进行日志记录)。这也可能有助于解决应用程序停机问题(静态实例的去初始化顺序)。
- 应用程序崩溃并显示"symbol _ZdlPvm, version Qt_5 not defined in file libQt5Core.so.5 with link time reference"
- 如何找出应用程序崩溃的原因 - Win 10 LTSB
- 操纵安卓相机的深度图导致应用程序崩溃
- 调用 java 的回调() 时应用程序崩溃.由于 detatchThread 而获得运行时错误
- QCompleter set模型使应用程序崩溃
- Qt 5 应用程序崩溃并出现"qLineEdit::setText"
- 切换NvAPI_Stereo_Deactivate/NvAPI_Stereo_activate会使unity应用程序崩溃
- eglSwapBuffers上的应用程序崩溃
- VLD 使应用程序崩溃
- 由于调用 std::condition_variable 后参数无效而导致应用程序崩溃
- 执行递归函数时 C++ 应用程序崩溃
- 在 C++/CLI/C# 项目中启用"Native Code Debugging"导致应用程序崩溃
- LOCAL_SHARED_LIBRARIES使我的应用程序崩溃
- 为什么使用 nullPtr 调用函数不会使我的应用程序崩溃
- 当删除上下文属性中的QLIST对象时,QT QML应用程序崩溃
- React 本机 0.59 应用程序崩溃并出现 libc 错误
- 当使用“制造”编译的程序中使用库时,应用程序崩溃
- 如何在导致应用程序崩溃的代码中修复指令
- C++多线程应用程序崩溃
- 当使用 /ENTRY:main 和 /MT 运行时库编译为 /SUBSYSTEM:WINDOWS 时,应用程序崩溃