一、背景
handler_ = std::make_shared<UsbServerEventHandler>(eventRunner_, pms);if (handler_ == nullptr) { USB_HILOGE(MODULE_USB_SERVICE, "Init failed due to create handler error"); return false;}
- 对此不同人有不同看法:
- 有些人认为应该判空,防止后面使用
handler_
的时候对空指针解引用。
- 有人认为,make_shared失败后会抛异常,且
handler
值是未定义的,判空实际无效。
二、探索
1、构造失败场景
思路
- 当前我们可以确定的是,
new(nothrow)
,能够申请到内存,并且出错后会返回nullptr
。
- 所以可以使用
new
将内存耗尽(包括虚拟内存),然后再调用make_shared
,这样就能够构造出失败的场景。
准备
Desktop free total used free shared buff/cache availableMem: 3986712 1072260 11960838116 2794844 2599996Swap: 2097148 3148 2094000➜ Desktop df -lh Filesystem Size Used Avail Use% Mounted ontmpfs 390M 3.4M 386M 1% /run/dev/sda3 98G 13G 80G 14% /tmpfs 2.0G 0 2.0G 0% /dev/shmtmpfs 5.0M 4.0K 5.0M 1% /run/lock/dev/sda2512M 5.3M 507M 2% /boot/efitmpfs 390M 104K 390M 1% /run/user/1001➜ Desktop uname -aLinux ubuntu 5.13.0-20-generic
- 所以我们需要耗尽所有的内存。
- 耗尽之后,在使用
make_shared
申请内存,使其出错。
#include #include #include using namespace std;struct Memory { uint8_t mem[UINT32_MAX];};int main(){ for (uint32_t count = 0; count < UINT32_MAX; ++count) { auto byte = new(nothrow) uint8_t[UINT32_MAX]; if (byte == nullptr) { cout << "new failed in loop: " << count <<endl; break; } } auto shared = make_shared<Memory>(); cout << "finished!" << endl; return 0;}
2、不同场景下验证
使用异常
- 编译,不做优化
clang++ make_shared.cpp -O0 -o make_shared
- 运行
./make_shared
➜ projects ./make_shared new failed in loop: 32766terminate called after throwing an instance of 'std::bad_alloc' what(): std::bad_alloc[1] 20796 IOT instruction (core dumped) ./make_shared
禁用异常
- 编译,不做优化
clang++ make_shared.cpp -O0 -o make_shared -fno-exceptions
- 运行
./make_shared
new failed in loop: 32766terminate called after throwing an instance of 'std::bad_alloc' what(): std::bad_alloc[1] 20836 IOT instruction (core dumped) ./make_shared
三、结论
- 通过上面的探索我们可以发现,不管在编译的时候是否禁用了异常,
make_shared
出错时,总会抛异常