如何检测对临时对象成员的引用

时间:2011-11-29 17:43:29

标签: c++

我的同事最近在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(),程序将发出错误警告

2 个答案:

答案 0 :(得分:2)

简单回答:一般来说,你无法捕获这些错误,原因是有类似的结构可能完全正常,因此编译器必须知道所有函数的语义才能警告你。

在更简单的情况下,就像获取临时地址一样,许多编译器已经警告过你,但在一般情况下,编译器知道它是非常困难的。

对于.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()示例也是如此,编译器不知道返回的引用是否是在表达式之后有效的对象。

所有这些属于未定义行为类别。

答案 1 :(得分:1)

查看此问题的解决方案,我认为它与您正在寻找的内容类似:

C++ catching dangling reference

  

有基于运行时的解决方案可以检测代码   无效的指针访问。到目前为止我只使用过mudflap(这是   从版本4.0开始集成在GCC中)。 mudflap试图追踪每一个   代码中的指针(和引用),如果是则检查每次访问   指针/引用实际上指向其基类型的活动对象。   这是一个例子:{...}