先看结论:Windows下可以调用空智能指针对象的函数,但是函数中访问目标对象的成员变量会崩溃,this指针为nullptr;Linux下Debug版本及不开优化版本也能正常运行,-O0以上优化版本访问空智能指针对象函数会发生崩溃。
问题起因:一个智能指针对象使用IsNull()判断是否为空后,执行函数,仅在Linux开优化(-O0以上)发生崩溃,代码如下:
#include <stdio.h>
#include <memory>
#include <assert.h>
class RawValue : public std::enable_shared_from_this<RawValue> {
public:
bool IsNull() {
printf("this:%x\n", this);
return this == nullptr;
}
int val_{0};
};
using NValue = std::shared_ptr<RawValue>;
int main() {
NValue null;
assert(null == nullptr);
assert(!null);
assert(null.get() == nullptr);
assert(null->IsNull());
null->IsNull();
//!!!crash assert(null->val_ == 0);
printf("---End---\n");
return 0;
}
Windows:Debug/Release/优化版本均正常运行。
Linux gcc:Debug/-O0正常运行;-O0以上崩溃。
感觉和编译器优化相关,根据反汇编推测如下:
不崩溃场景:调用编译好非虚函数,传this指针,仅仅访问空指针this本身不崩溃,不能访问目标对象实际的成员。
崩溃的场景:函数事先没有加载,需要通过对象指针拿到函数偏移才能调用。
因此,上例中的IsNull的写法不推荐,最好使用if(null)直接判断智能指针是否为空。