【问题标题】:How to manually throw a compiler error in GCC and Xcode如何在 GCC 和 Xcode 中手动抛出编译器错误
【发布时间】:2010-06-08 02:44:37
【问题描述】:

在 xcode 中,在使用 gcc 编译应用程序时,如果 NSZombieEnabled 之类的功能在分发版本中打开,我想抛出编译时错误,从而确保编译将失败并且我不会意外地做一些愚蠢的事情。

我做了一些谷歌搜索,但无法弄清楚如果满足某个条件,如何使编译器退出。肯定很简单吧,我是不是没找到?

【问题讨论】:

    标签: iphone objective-c xcode gcc compiler-construction


    【解决方案1】:

    使用the #error directive:

    #if SHOULD_FAIL
    #error "bad compiler!"
    #endif
    
    int main()
    {
        return 0;
    }
    
    $ gcc a.c -DSHOULD_FAIL=0 #顺利通过 $ gcc a.c -DSHOULD_FAIL=1 a.c:2:2: 错误:#error“错误的编译器!”

    由于NSZombieEnabled 是一个环境变量,您需要在构建脚本中做一些巧妙的事情来将您的宏定义为零或一。

    严格来说,#error 指令出现在 C 预处理器中,而不是 gcc。但在你描述的情况下,这应该无关紧要。

    【讨论】:

    • 这似乎很难……似乎找不到方法
    • @coneybeare:NSZombieEnabled 是您在运行时设置的环境变量。您无需在编译时担心它。但是,如果您有编译时调试宏,则此技术很有用。
    • +1 请注意,您也可以通过#warning This is a warning 发出警告而不是错误。
    【解决方案2】:

    NSZombieEnabled 是一个环境标志,据我所知,它不会影响生成的二进制文件(尽管它可能会影响编译速度。)

    【讨论】:

      【解决方案3】:

      一个编译时断言()--a.k.a.静态断言——可能会有所帮助。这是我的,主要来自http://www.pixelbeat.org/programming/gcc/static_assert.html

      /*-----------------------------------------------------------------------------
       *  Compile-time ASSERT(). Similar to the BOOST_STATIC_ASSERT(). And the C++0x
       *  static_assert(), which also has a parameter for a useless error message
       *  (see correction!). Our ASSERT() can be placed anywhere in the code, except:
       *
       *  o In a twice-included header file, without a #ifndef...#endif wrapper.
       *  o In the middle of a structure definition (or enum definition).
       *  o In C89 or C90, after a statement. But you can wrap it in braces!
       *
       *  If you want stick something in the middle of a structure definition
       *  you'll need to use the ugly, three-line construct #if...#error...#endif.
       *  And if you do do this, the pre-processor has a much more limited idea of
       *  what a "constant expression" is.
       *
       *  This is a refinement of ideas from the web (www.pixebeat.org is good). It
       *  is shorter than BOOST. And, I believe, is better than Linus Torvald's
       *  suggestion for an improved BUILD_BUG_ON(). And the do{...}while(0) wrapper
       *  you commonly see is totally inapplicable here: it limits permissible
       *  locations.
       *
       *  The web has many suggestions using arrays with a negative index. But with
       *  GCC, most of these do not detect a NON-CONSTANT arg (which is easy enough
       *  to do in error), except for the attractive 'extern int foo[expression]',
       *  which also gives an 'unused variable' warning (which might be fixable via
       *  (void)foo). GCC 4.3 apparently has a built-in static_assert(). Update:
       *  typedef int array[expression] seems also to be good.
       */
      #define CONCAT_TOKENS(a, b) a ## b
      #define EXPAND_THEN_CONCAT(a,b) CONCAT_TOKENS(a, b)
      #define ASSERT(e) enum {EXPAND_THEN_CONCAT(ASSERT_line_,__LINE__) = 1/!!(e)}
      

      但我更正了我对 C++0x 中“无用”消息的看法:

      /*-----------------------------------------------------------------------------
       *  Correction!: The message in static_assert() isn't quite useless, and we've
       *  added it to ASSERTM(). This is needed for the case where two different
       *  header files happen by chance to have two ASSERT()'s on the same line, or
       *  likewise for a source file and a header file.
       *
       *  We could also handle this via __COUNTER__, but this isn't supported by
       *  the SGI compiler (and is uglier). And we can't use __FILE__, because it
       *  doesn't usually expand to a valid C token (e.g. it has a dot c or dot h).
       */
      #define ASSERTM(e,m) enum{EXPAND_THEN_CONCAT(m##_ASSERT_line_,__LINE__)=1/!!(e)}
      

      一些例子:

      /*-----------------------------------------------------------------------------
       *  Example:
       */
      ASSERTM (sizeof (int16) == 2, my_global_header_h);
      ASSERTM (sizeof (ord32) == 4, my_global_header_h);
      ASSERTM (sizeof (int64) == 8, my_global_header_h);
      
      /*-----------------------------------------------------------------------------
       *  Equally good, I believe, is the following variant, but it is slightly
       *  longer (and not used by us at the present time):
       */
      #define ASSERTt(e) typedef int EXPAND_THEN_CONCAT(ASSERT_line_,__LINE__)[1-2*!(e)]
      

      【讨论】:

        【解决方案4】:

        您可以做的另一件有趣的事情是操纵构建脚本的输出。如果您在构建过程中使用自定义构建脚本,则可以执行以下操作:

        echo "error: this build step failed!"
        

        或者:

        echo "warning: this build step could be potentially faulty"
        

        这些将产生错误或警告(分别)将显示在构建结果窗口中。我已经用过几次了,它真的很有用。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-08-02
          • 2021-09-19
          • 1970-01-01
          • 2012-01-28
          • 2014-12-12
          相关资源
          最近更新 更多