我正在开发一个用于编程竞赛(如LeetCode、Codeforces等)的在线评测系统。对于大多数编程竞赛,C/C++中不允许内联汇编程序,所以我想在我的系统中添加同样的限制。
我想让GCC和G++在编译包含内联汇编程序的C/C++程序时产生错误,这样任何包含内联汇编程序的代码都会导致编译错误。
有办法做到这一点吗?我应该把一些命令行参数传递给GCC/G++吗?
注意:禁用内联汇编程序只是为了遵守规则,而不是出于安全考虑。
发布于 2019-03-16 01:26:31
有没有办法禁用GCC的内联汇编程序?
有几种方法。
关闭编译器中的程序集
若要在编译阶段执行此操作,请使用参数-fno-asm。但是,请记住,这只会影响asm,而不会影响__asm__。
文档:
-fno-asm不要将"asm“、"inline”或"typeof“识别为关键字,以便代码可以使用这些单词作为标识符。您可以使用关键字"__asm__“、"__inline__”和"__typeof__“。-ansi暗示着-fno-asm。 在C++中,此开关只影响"typeof“关键字,因为"asm”和"inline“是标准关键字。您可能需要使用-fno-gnu-keywords标志,这具有相同的效果。在C99模式(-std=c99或-std=gnu99)中,此开关只影响"asm“和"typeof”关键字,因为"inline“是ISO C99中的标准关键字。
定义宏
您可以使用参数-Dasm=error -D__asm__=error
请注意,此结构是通用的。它所做的就是创建宏。它的工作原理很像一个#define。文件上说:
-D name=definition定义的内容被标记化和处理,就像它们出现在翻译阶段第三阶段的#define指令中一样。特别是,定义将被嵌入的换行符截断。 ..。
因此,它所做的只是将asm或__asm__的出现更改为error。这是在预处理阶段完成的。您不必使用error。只要选择不编译的东西就行了。
使用在编译期间触发的宏。
在编译阶段使用宏解决这个问题的方法,正如zwol注释中所建议的那样,您可以使用-D'asm(...)=_Static_assert(0,"inline assembly not allowed")'。如果存在一个名为error的标识符,这也将解决这个问题。
注意:这种方法需要-std=c11或更高版本。
在使用gcc之前使用grep
解决问题的另一种方法可能是在编译之前先在源树的根中执行一个grep:
grep -nr "asm"这也会捕获__asm__,但它可能会给出假阳性,例如,您有一个包含子字符串"asm"的字符串文本、标识符或注释。但是在您的例子中,您也可以通过在源代码中任何地方禁止出现该字符串来解决这个问题。只要改变规则就行。
可能的意外问题
注意,禁用程序集可能会导致其他问题。例如,我不能在这个选项中使用stdio.h。通常,系统标头包含内联程序集代码。
一种欺骗上述方法的方法
可以以机器代码的形式执行字符串。有关示例,请参见此答案:https://stackoverflow.com/a/18477070/6699433
以上链接中的一段代码:
/* our machine code */
char code[] = {0x55,0x48,0x89,0xe5,0x89,0x7d,0xfc,0x48,
0x89,0x75,0xf0,0xb8,0x2a,0x00,0x00,0x00,0xc9,0xc3,0x00};
/* copy code to executable buffer */
void *buf = mmap (0,sizeof(code),PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_PRIVATE|MAP_ANON,-1,0);
memcpy (buf, code, sizeof(code));
/* run code */
int i = ((int (*) (void))buf)();上面的代码只是想给出一个关于如何欺骗OP所规定的规则的快速概念。这并不是一个好的例子,如何实际执行它在现实中。此外,代码不是我的。这只是我提供的链接中的一个简短的代码引用。如果你对如何改进它有自己的想法,那么请评论一下4py 0:s的原始帖子。
https://stackoverflow.com/questions/55192591
复制相似问题