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::cout
      std::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;
      }