简体   繁体   English

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

[英]how to detect references to members of temporary objects

My colleague recently compiled our program in Windows, and discovered a bug of the sort: 我的同事最近在Windows中编译了我们的程序,并发现了这种类型的错误:

  std::string a = "hello "; 
  std::string b = "world"; 
  const char *p = (a+b).c_str();
  printf("%s\n", p);

which for some reason did not crash in our Linux executables. 由于某种原因,我们的Linux可执行文件中没有崩溃。

None of our compilers give any kind of warning, so we are now worried that this error might exist in the code. 我们的编译器都没有给出任何警告,因此我们现在担心代码中可能存在此错误。

Although we can grep for c_str() occurrences and do a visual inspection, there is a possibility that one might have also done the following: 虽然我们可以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
};

and accessed it like: 并访问它像:

  I& a = X().get();         // will get a reference to a temporary, or a valid copy?
  cout << a.num;

instead of : 代替 :

 cout << X().get().num;   

which is safe (isn't it?) 哪个是安全的(不是吗?)

Question: Is there a way I can catch such errors (perhaps using the compiler, or even an assertion) ? 问题:有没有办法可以捕获这些错误(可能使用编译器,甚至是断言)?
I need to be sure that if author of struct X changes get() between version 1 and 2 that the program will warn for the error 我需要确保如果struct X作者在版本1版本 2之间更改get() ,程序将警告错误

Simple answer: In general you cannot catch those errors, and the reason is that there are similar constructs that might be perfectly fine, so the compiler would have to know the semantics of all the functions to be able to warn you. 简单回答:一般来说,你无法捕获这些错误,原因是有类似的结构可能完全正常,因此编译器必须知道所有函数的语义才能警告你。

In simpler cases, like obtaining the address of a temporary, many compilers already warn you, but in the general case, it is quite difficult if not impossible for the compiler to know. 在更简单的情况下,比如获取临时地址,许多编译器已经警告过你,但在一般情况下,编译器很难知道。

For some similar example to the .c_str() consider: 对于.c_str()一些类似示例,请考虑:

std::vector< const char * > v;
v.push_back( "Hi" );
const char* p = *v.begin();

The call to begin returns a temporary, similar to the expression (a+b) , and you are calling a member function of that temporary ( operator* ) that returns a const char* , which is quite similar to your original case (from the point of view of the types involved). begin的调用返回一个临时的,类似于表达式(a+b) ,并且你正在调用一个返回const char*临时( operator* )的成员函数,这与你原来的情况非常相似(来自于涉及的类型的观点)。 The problem is that in this case the pointee is still valid after the call, while in yours ( .c_str() ) it isn't, but it is part of the semantics of the operation, not the syntax that the compiler can check for you. 问题是,在这种情况下,指针对象在调用之后仍然有效,而在你的( .c_str() )它不是,但它是操作语义的一部分,而不是编译器可以检查的语法您。 The same goes for the .get() example, the compiler does not know if the returned reference is to an object that will be valid after the expression or not. 对于.get()示例也是如此,编译器不知道返回的引用是否是在表达式之后有效的对象。

All these fall under the category of Undefined Behavior. 所有这些都归入未定义行为的范畴。

Check out this question's solution, I think it does something similar to what you're looking for: 看看这个问题的解决方案,我认为它与您正在寻找的类似:

C++ catching dangling reference C ++抓住悬空参考

There are runtime based solutions which instrument the code to check invalid pointer accesses. 有基于运行时的解决方案,用于检测代码以检查无效指针访问。 I've only used mudflap so far (which is integrated in GCC since version 4.0). 到目前为止我只使用过mudflap(自4.0版以来就集成在GCC中)。 mudflap tries to track each pointer (and reference) in the code and checks each access if the pointer/reference actually points to an alive object of its base type. mudflap尝试跟踪代码中的每个指针(和引用),如果指针/引用实际指向其基类型的活动对象,则检查每次访问。 Here is an example: {...} 这是一个例子:{...}

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

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