如何检测对临时对象成员的引用
how to detect references to members of temporary objects
我的同事最近在Windows上编译我们的程序,发现了一个类似的错误:
std::string a = "hello ";
std::string b = "world";
const char *p = (a+b).c_str();
printf("%sn", p);
由于某些原因在我们的Linux可执行文件中没有崩溃。
我们的编译器都没有给出任何警告,所以我们现在担心这个错误可能存在于代码中。
虽然我们可以grep查找c_str()
的出现并进行目视检查,但有可能还做了以下操作:
struct I {
int num;
I() { num=0; }
};
struct X {
I *m;
X() { m = new I; }
~X() { delete m; }
I get() { return *m; } // version 1, or
I& get() { return *m; } // version 2
};
并像这样访问它:
I& a = X().get(); // will get a reference to a temporary, or a valid copy?
cout << a.num;
代替:
cout << X().get().num;
哪个是安全的(不是吗?)
问题:是否有一种方法可以捕获这样的错误(可能使用编译器,甚至断言)?
我需要确保如果struct X
的作者在版本1和2之间更改get()
,程序将警告错误
简单的回答:一般来说,您无法捕获这些错误,原因是存在类似的结构,这些结构可能完全没有问题,因此编译器必须知道所有函数的语义才能向您发出警告。
在更简单的情况下,比如获取临时地址,许多编译器已经警告你了,但在一般情况下,编译器很难知道,如果不是不可能的话。
对于.c_str()
的一些类似示例,请考虑:
std::vector< const char * > v;
v.push_back( "Hi" );
const char* p = *v.begin();
对begin
的调用返回一个临时对象,类似于表达式(a+b)
,并且您正在调用该临时对象(operator*
)的成员函数,该成员函数返回const char*
,这与您的原始情况非常相似(从所涉及的类型的角度来看)。问题是,在这种情况下,指针在调用后仍然有效,而在您的(.c_str()
)中则不是,但它是操作语义的一部分,而不是编译器可以为您检查的语法。.get()
的例子也是如此,编译器不知道返回的引用是否指向一个在表达式之后有效的对象。
看看这个问题的解决方案,我认为它做了一些类似于你正在寻找的东西:
c++捕获悬空引用
有基于运行时的解决方案来检测代码无效的指针访问。到目前为止,我只使用过挡泥板(这是从4.0版开始集成在GCC中)。泥板试图追踪每一个指针(和引用),并检查每次访问是否指针/引用实际上指向其基类型的活动对象。下面是一个例子:{…}
- 指向设备对象成员的指针
- 在不复制临时对象的情况下延长其生存期
- 为什么当我们有常量引用时创建临时对象?
- 程序如何'remember'临时对象?
- 返回对临时对象的引用
- 防止临时对象文件访问 MSVC 中的磁盘
- 是否可以在C++中移动临时对象的属性?
- 通过引用传递临时对象
- C++:允许临时对象调用非常量成员函数的设计理念是什么?
- 如果类没有任何成员变量,则通过临时对象调用类的成员函数的开销是多少?
- 检查成员函数是否返回临时对象或数组对象
- C++临时对象成员函数的生存期
- 是否可以从成员函数中检测对象是否为临时对象
- 我可以访问临时对象的成员吗?
- 传递给存储常量引用的成员的临时对象的生存期
- C++:通过引用将 std::vector<> 成员返回到临时对象
- 我应该创建一个临时对象来实例化C++中的成员变量吗
- 临时对象的成员函数的左值引用返回是否为悬空引用
- 返回对临时对象成员的const引用
- 如何检测对临时对象成员的引用