我正在为LeetCode,Codeforces等编程竞赛开发一个在线评判系统。对于大多数编程竞赛,在C / C ++中不允许使用内联汇编程序,所以我想对我的系统添加相同的限制。
我想在编译包含内联汇编程序的C / C ++程序时让GCC和G ++产生错误,这样任何包含内联汇编程序的代码都会导致编译错误。
有没有办法实现这一目标?我应该将一些命令行参数传递给GCC / G ++吗?
注意:禁用内联汇编程序只是为了遵守规则,而不是出于安全考虑。
是的,有几种方法。
要在编译阶段执行此操作,请使用参数-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指令的翻译阶段3中出现一样。特别是,定义将被嵌入的换行符截断。
...
所以它的作用只是将asm
或__asm__
的出现改为error
。这是在预处理器阶段完成的。你不必使用error
。只需挑选任何无法编译的东西。
如zwol的评论中所建议的那样,在编译阶段使用宏来解决它的方法,你可以使用-D'asm(...)=_Static_assert(0,"inline assembly not allowed")'
。如果存在名为error
的标识符,这也将解决问题。
注意:此方法需要-std=c11
或更高版本。
另一种可能解决问题的方法是在编译之前在源树的根目录中执行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规定的规则。它并不是一个如何在现实中实际执行它的好例子。此外,代码不是我的。它只是我提供的链接的简短代码报价。如果您有关于如何改进它的想法,那么请评论4pie0:s原始帖子。