如何在 GCC 和 Xcode 中手动抛出编译器错误
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2994490/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to manually throw a compiler error in GCC and Xcode
提问by coneybeare
In xcode, while compiling apps with gcc, I want to throw compilation time errors if things like NSZombieEnabled is on for a distribution release, thus ensuring that compilation will fail and I won't accidentally do something stupid.
在 xcode 中,在使用 gcc 编译应用程序时,如果诸如 NSZombieEnabled 之类的东西在发行版中启用,我想抛出编译时间错误,从而确保编译会失败并且我不会意外地做一些愚蠢的事情。
I did some googling, but could not figure out how to cause the compiler to bail if a certain condition is met. Surely it must be easy, am I just not finding it?
我做了一些谷歌搜索,但无法弄清楚如果满足某个条件,如何使编译器保释。当然它一定很容易,我只是没有找到它吗?
回答by Mark Rushakoff
Use the #errordirective:
使用的#error指令:
#if SHOULD_FAIL
#error "bad compiler!"
#endif
int main()
{
return 0;
}
$ gcc a.c -DSHOULD_FAIL=0 # passes fine $ gcc a.c -DSHOULD_FAIL=1 a.c:2:2: error: #error "bad compiler!"
Since NSZombieEnabledis an environment variable, you'll need to do something clever in your build script to define your macro as zero or one.
由于NSZombieEnabled是一个环境变量,您需要在构建脚本中做一些聪明的事情来将宏定义为零或一。
Strictly speaking, the #errordirective occurs in the C Preprocessor, not gcc. But that shouldn't matter in the case you've described.
严格来说,该#error指令出现在 C 预处理器中,而不是gcc. 但这在你描述的情况下应该无关紧要。
回答by Joseph Quinsey
A complile-time assert()--a.k.a. static assert--may be helpful. Here is mine, derived mostly from http://www.pixelbeat.org/programming/gcc/static_assert.html:
编译时 assert()——又名静态断言——可能会有所帮助。这是我的,主要来自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)}
But I corrected my opinion about the 'useless' message in C++0x:
但我更正了我对 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)}
Some examples:
一些例子:
/*-----------------------------------------------------------------------------
* 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)]
回答by fbrereto
NSZombieEnabledis an environment flag and, to my knowledge, should not affect the resulting binary (though it may affect the speed of the compilation.)
NSZombieEnabled是一个环境标志,据我所知,不应影响生成的二进制文件(尽管它可能会影响编译速度。)
回答by Dave DeLong
Another interesting thing you can do is manipulate the output of your build script. If you're using a custom build script as part of your build process, you can do something like:
您可以做的另一件有趣的事情是操作构建脚本的输出。如果您在构建过程中使用自定义构建脚本,您可以执行以下操作:
echo "error: this build step failed!"
Or:
或者:
echo "warning: this build step could be potentially faulty"
Those will produce errors or warnings (respectively) that will show up in the build results window. I've used this a couple times, and it's reallyuseful.
这些将产生错误或警告(分别)并显示在构建结果窗口中。我已经用过几次了,它真的很有用。

