检测到临时的悬挂引用
Clang 3.9非常重用临时用户使用的内存。
Clang 3.9 extremely reuses memory used by temporaries.
此代码为UB(简化代码):
This code is UB (simplified code):
template <class T>
class my_optional
{
public:
bool has{ false };
T value;
const T& get_or_default(const T& def)
{
return has ? value : def;
}
};
void use(const std::string& s)
{
// ...
}
int main()
{
my_optional<std::string> m;
// ...
const std::string& s = m.get_or_default("default value");
use(s); // s is dangling if default returned
}
我们有大量类似上面的代码( my_optional
只是一个简单的示例来说明它。)
We have tons of code something like above (my_optional
is just a simple example to illustrate it).
由于UB从3.9开始,所有clang编译器重用此内存,这是合法行为。
Because of UB all clang compiler since 3.9 starts to reuse this memory, and it is lawful behavior.
问题是:如何在编译时或使用消毒剂之类的检测此类悬挂引用在运行时?没有clang消毒剂可以检测到它们。
The question is: how to detect such dangling references at compile time or with something like sanitizer at runtime? No clang sanitizer can detect them.
已更新。请不要回答:使用 std :: optional
。请仔细阅读:问题不在于此。
Upd2。请不要回答:您的代码设计不好。仔细阅读:问题与代码设计无关。
Upd. Please do not answer: "use std::optional
". Read carefully: question is NOT about it.
Upd2. Please do not answer: "your code design is bad". Read carefully: question is NOT about code design.
您可以通过添加额外的重载来检测对该特定API的滥用:
You can detect misuses of this particular API by adding an additional overload:
const T& get_or_default(T&& rvalue) = delete;
如果给 get_or_default
的自变量是真正的右值,将选择它,因此编译将失败。
If the argument given to get_or_default
is a true rvalue, it will be chosen instead, so compilation will fail.
关于在运行时检测此类错误,请尝试使用Clang的AddressSanitizer和use-after-return( ASAN_OPTIONS = detect_stack_use_after_return = 1
)和/或范围后使用( -fsanitize-address-use-after-scope
)检测已启用。
As for detecting such errors at runtime, try using Clang's AddressSanitizer with use-after-return (ASAN_OPTIONS=detect_stack_use_after_return=1
) and/or use-after-scope (-fsanitize-address-use-after-scope
) detection enabled.