[英]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("%s\n", 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)
,并且你正在调用一个返回const char*
临时( operator*
)的成员函数,这与你原来的情况非常相似(来自于涉及的类型的观点)。 问题是,在这种情况下,指针对象在调用之后仍然有效,而在你的( .c_str()
)它不是,但它是操作语义的一部分,而不是编译器可以检查的语法您。 对于.get()
示例也是如此,编译器不知道返回的引用是否是在表达式之后有效的对象。
所有这些都归入未定义行为的范畴。
看看这个问题的解决方案,我认为它与您正在寻找的类似:
有基于运行时的解决方案,用于检测代码以检查无效指针访问。 到目前为止我只使用过mudflap(自4.0版以来就集成在GCC中)。 mudflap尝试跟踪代码中的每个指针(和引用),如果指针/引用实际指向其基类型的活动对象,则检查每次访问。 这是一个例子:{...}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.