繁体   English   中英

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

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

所有这些都归入未定义行为的范畴。

看看这个问题的解决方案,我认为它与您正在寻找的类似:

C ++抓住悬空参考

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM