C++ Clang无法检测未定义的行为
如何在下面的示例中检测未定义的行为C++ Clang无法检测未定义的行为,c++,undefined-behavior,clang++,C++,Undefined Behavior,Clang++,如何在下面的示例中检测未定义的行为 #include <iostream> #include <stream> int main() { std::cout << "Undefined: " << std::string().front() << std::endl; return 0; } 相关的,相关的问题: (但我对这种特殊的未定义行为感兴趣。) 将鲍姆-麻省理工学院-奥根的链接转化为答案 在使用GCC wor
#include <iostream>
#include <stream>
int main() {
std::cout << "Undefined: " << std::string().front() << std::endl;
return 0;
}
相关的,相关的问题:
- (但我对这种特殊的未定义行为感兴趣。)
- 将鲍姆-麻省理工学院-奥根的链接转化为答案
在使用GCC works编译时添加标志
-D_GLIBCXX_DEBUG-D_GLIBCXX_DEBUG_PEDANTIC
。同样的方法不适用于叮当声
这将在std::basic_string
内启用运行时检查
结果(为清晰起见添加了换行符):
$/usr/local/Cellar/gcc/7.2.0/bin/g++-7 main.cc-g-D\u GLIBCXX\u DEBUG-D\u GLIBCXX\u DEBUG\u PEDANTIC
美元/年
未定义:
/usr/local/ceral/gcc/7.2.0/include/c++/7.2.0/bits/basic_string.h:1077:
std::\uuuCXX11::基本字符串::引用
std::\uuuCXX11::基本字符串::前端()
[with_CharT=char;_Traits=std::char_Traits;
_Alloc=std::分配器;
std::uucxx11::基本_string::reference=char&]:
断言'!empty()'失败。
[1] 24143中止。/a.out
将Baum-mit-Augen的链接转化为答案
在使用GCC works编译时添加标志-D_GLIBCXX_DEBUG-D_GLIBCXX_DEBUG_PEDANTIC
。同样的方法不适用于叮当声
这将在std::basic_string
内启用运行时检查
结果(为清晰起见添加了换行符):
$/usr/local/Cellar/gcc/7.2.0/bin/g++-7 main.cc-g-D\u GLIBCXX\u DEBUG-D\u GLIBCXX\u DEBUG\u PEDANTIC
美元/年
未定义:
/usr/local/ceral/gcc/7.2.0/include/c++/7.2.0/bits/basic_string.h:1077:
std::\uuuCXX11::基本字符串::引用
std::\uuuCXX11::基本字符串::前端()
[with_CharT=char;_Traits=std::char_Traits;
_Alloc=std::分配器;
std::uucxx11::基本_string::reference=char&]:
断言'!empty()'失败。
[1] 24143中止。/a.out
编译时警告并不总是适用于标准容器,但实现自由函数将允许额外的检查,可以选择使用编译器标志关闭这些检查
#define NDEBUG
#include <iostream>
#include <string>
#include <cassert>
#include <stdexcept>
struct assert_on_failure
{
template<class ErrorMessage>
void check(bool condition, ErrorMessage&& msg) const
{
if (!condition)
assert(!msg);
}
};
struct throw_on_failure
{
template<class ErrorMessage>
void check(bool condition, ErrorMessage&& msg) const
{
if (!condition)
throw std::runtime_error(msg);
}
};
#ifdef NDEBUG
constexpr auto default_failure_policy = throw_on_failure{};
#else
constexpr auto default_failure_policy = assert_on_failure{};
#endif
template
<
class Container,
class FailurePolicy = std::add_lvalue_reference_t<decltype(default_failure_policy)>
>
decltype(auto) get_front(Container&& cont,
FailurePolicy&& policy = default_failure_policy)
{
policy.check(cont.size() > 0, "container is empty");
return cont.front();
}
int main() {
std::cout << "Undefined: " << get_front(std::string()) << std::endl;
return 0;
}
#定义NDEBUG
#包括
#包括
#包括
#包括
结构在\u失败时断言\u
{
模板
无效检查(布尔条件、错误消息和消息)常量
{
如果(!条件)
断言(!msg);
}
};
结构在失败时抛出
{
模板
无效检查(布尔条件、错误消息和消息)常量
{
如果(!条件)
抛出std::运行时错误(msg);
}
};
#ifdef-NDEBUG
constexpr auto default_failure_policy=throw_on_failure{};
#否则
constexpr auto default_failure_policy=assert_on_failure{};
#恩迪夫
模板
<
类容器,
class FailurePolicy=std::添加\u左值\u引用\u t
>
decltype(自动)获取前端(容器和控制),
FailurePolicy&&policy=默认\u故障\u策略)
{
检查(cont.size()>0,“容器为空”);
返回控制前();
}
int main(){
标准容器并不总是可能出现编译时警告,但实现自由函数将允许额外的检查,可以选择使用编译器标志关闭这些检查
#define NDEBUG
#include <iostream>
#include <string>
#include <cassert>
#include <stdexcept>
struct assert_on_failure
{
template<class ErrorMessage>
void check(bool condition, ErrorMessage&& msg) const
{
if (!condition)
assert(!msg);
}
};
struct throw_on_failure
{
template<class ErrorMessage>
void check(bool condition, ErrorMessage&& msg) const
{
if (!condition)
throw std::runtime_error(msg);
}
};
#ifdef NDEBUG
constexpr auto default_failure_policy = throw_on_failure{};
#else
constexpr auto default_failure_policy = assert_on_failure{};
#endif
template
<
class Container,
class FailurePolicy = std::add_lvalue_reference_t<decltype(default_failure_policy)>
>
decltype(auto) get_front(Container&& cont,
FailurePolicy&& policy = default_failure_policy)
{
policy.check(cont.size() > 0, "container is empty");
return cont.front();
}
int main() {
std::cout << "Undefined: " << get_front(std::string()) << std::endl;
return 0;
}
#定义NDEBUG
#包括
#包括
#包括
#包括
结构在\u失败时断言\u
{
模板
无效检查(布尔条件、错误消息和消息)常量
{
如果(!条件)
断言(!msg);
}
};
结构在失败时抛出
{
模板
无效检查(布尔条件、错误消息和消息)常量
{
如果(!条件)
抛出std::运行时错误(msg);
}
};
#ifdef-NDEBUG
constexpr auto default_failure_policy=throw_on_failure{};
#否则
constexpr auto default_failure_policy=assert_on_failure{};
#恩迪夫
模板
<
类容器,
class FailurePolicy=std::添加\u左值\u引用\u t
>
decltype(自动)获取前端(容器和控制),
FailurePolicy&&policy=默认\u故障\u策略)
{
检查(cont.size()>0,“容器为空”);
返回控制前();
}
int main(){
std::coutstd::string()。at(0)
谢谢,@BaummitAugen。我把你的评论变成了一个答案。另请参阅相关讨论。clang/libc++已经开始使用类似的调试模式,但这方面的开发似乎已经停滞了好几年。std::string()。at(0)
谢谢你,@BaummitAugen。我把你的评论变成了一个答案。另请参阅相关讨论。clang/libc++已经开始使用类似的调试模式,但它的开发似乎已经死了好几年。谢谢你,@richard hodges!这也适用于clang++。你的解决方案的好处是它可以关闭,并且可以在然而,我的问题和动机是让编译器(或其他工具)检测这个UB(编译时或运行时)——这排除了(对我来说)在调用UB的地方编写/更改代码。您的解决方案无疑是修改代码的一种优雅方式。我仍然需要将所有front
调用更改为get_front
。谢谢您,@richard hodges!这也适用于Clang++。您的解决方案的好处是它可以关闭并适用于所有容器。但是,我的问题和动机是让编译器(或其他工具)检测这个UB(编译时或运行时)——这就排除了(对我来说)在调用UB的地方编写/更改代码。您的解决方案当然是修改代码的一种优雅方式。我仍然需要更改所有front
调用以get\u front
。
#define NDEBUG
#include <iostream>
#include <string>
#include <cassert>
#include <stdexcept>
struct assert_on_failure
{
template<class ErrorMessage>
void check(bool condition, ErrorMessage&& msg) const
{
if (!condition)
assert(!msg);
}
};
struct throw_on_failure
{
template<class ErrorMessage>
void check(bool condition, ErrorMessage&& msg) const
{
if (!condition)
throw std::runtime_error(msg);
}
};
#ifdef NDEBUG
constexpr auto default_failure_policy = throw_on_failure{};
#else
constexpr auto default_failure_policy = assert_on_failure{};
#endif
template
<
class Container,
class FailurePolicy = std::add_lvalue_reference_t<decltype(default_failure_policy)>
>
decltype(auto) get_front(Container&& cont,
FailurePolicy&& policy = default_failure_policy)
{
policy.check(cont.size() > 0, "container is empty");
return cont.front();
}
int main() {
std::cout << "Undefined: " << get_front(std::string()) << std::endl;
return 0;
}