一、背景
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 available
Mem: 3986712 1072260 119608 38116 2794844 2599996
Swap: 2097148 3148 2094000
➜ Desktop df -lh
Filesystem Size Used Avail Use% Mounted on
tmpfs 390M 3 .4M 386M 1 % /run
/dev/sda3 98G 13G 80G 14 % /
tmpfs 2 .0G 0 2 .0G 0 % /dev/shm
tmpfs 5 .0M 4 .0K 5 .0M 1 % /run/lock
/dev/sda2 512M 5 .3M 507M 2 % /boot/efi
tmpfs 390M 104K 390M 1 % /run/user/1001
➜ Desktop uname -a
Linux ubuntu 5.13 .0-20-generic
所以我们需要耗尽所有的内存。 耗尽之后,在使用make_shared
申请内存,使其出错。
# include <iostream>
# include <cstdint>
# include <memory>
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: 32766
terminate 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: 32766
terminate called after throwing an instance of 'std::bad_alloc'
what( ) : std::bad_alloc
[ 1 ] 20836 IOT instruction ( core dumped) ./make_shared
三、结论
通过上面的探索我们可以发现,不管在编译的时候是否禁用了异常,make_shared
出错时,总会抛异常