【发布时间】:2018-10-26 15:09:28
【问题描述】:
根据 C 标准,如果程序定义或声明了保留标识符,则行为未定义。一类保留标识符是在 C 标准库中定义的具有外部链接的标识符。
对于具有未定义行为的程序,请考虑以下情况:file1.c 定义了一个名为 time 的具有外部链接的变量,它与 time.h 中声明的标准库中的 time 函数冲突。
file1.c:
int time;
int foo( void )
{
return time;
}
file2.c:
#include <time.h>
#include <stdio.h>
extern int foo( void );
int main( void )
{
foo();
printf( "current time = %ld\n", time( NULL ) );
return 0;
}
当程序编译并运行时,会发生段错误,因为 file2.c 中引用的time 符号链接到 file1.c 中的time 变量,而不是 C 库中的函数。
$ gcc -c -o file1.o file1.c
$ gcc -c -o file2.o file2.c
$ gcc -o test file1.o file2.o
$ ./test
Segmentation fault (core dumped)
我想知道 GCC 是否有任何方法可以在编译或链接时检测用户代码中冲突的保留标识符的使用。这是我的动机:我正在开发一个应用程序,用户可以在其中为应用程序编写 C 扩展,这些扩展被编译并链接到应用程序的其余部分。如果用户的 C 代码像上面的示例一样使用保留标识符,则生成的程序可能会以难以预测的方式失败。
想到的一个解决方案是在用户的目标文件上运行 nm 之类的东西,并将定义的符号与 C 库中的保留标识符列表进行比较。但是,我希望在 GCC 中找到可以检测到问题的东西。有谁知道这是否可行,或者有什么建议?
【问题讨论】:
-
好问题。事实上,GCC 能够警告许多标识符,特别是隐式声明不符合标准,但不是关于这个。
-
您可以从禁止全局变量开始。 gcc 应该能够在同一个翻译单元中检测与标准库的冲突。
-
或制作一个简单的解析器,检查用户导出的符号是否遵循可以禁用任何阴影的简单语法。例如。强制所有用户的全局符号以
usr_或其他东西为前缀 -
这并不是编译器可以给出错误的任何东西,因为它只处理translation units。链接器可能能够做到这一点,但是对于 C 来说,符号只是一个符号,实际上没有关于符号的语义信息可供链接器检测到。
-
另一种选择:将所有代码编写为库代码,将所有导出的标识符正确命名为命名空间前缀,问题不再存在。