Clang 3.9 极大地重用了临时使用的内存。
此代码为UB(简化代码):
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
只是一个简单的例子来说明它)。
因为UB所有clang编译器从3.9开始重用这 block 内存,是合法的行为。
问题是:如何在编译时检测这种悬空引用,或者在运行时使用 sanitizer 之类的东西?没有 clang sanitizer 可以检测到它们。
更新。请不要回答:“使用 std::optional
”。仔细阅读:问题与它无关。
更新2。请不要回答:“你的代码设计不好”。仔细阅读:问题与代码设计无关。
最佳答案
您可以通过添加额外的重载来检测此特定 API 的滥用情况:
const T& get_or_default(T&& rvalue) = delete;
如果提供给 get_or_default
的参数是一个真正的右值,它将被选择,因此编译将失败。
至于在运行时检测此类错误,请尝试将 Clang 的 AddressSanitizer 与 use-after-return (ASAN_OPTIONS=detect_stack_use_after_return=1
) 和/或 use-after-scope (-fsanitize- address-use-after-scope
) 检测已启用。
关于c++ - 检测对临时的悬空引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42340073/