2010-07-08 83 views
1

我想知道静态变量或函数如何被保护,只用于它定义的文件。我知道这样的变量和函数是在数据部分(堆区确切地说),但它是用文件名标记的吗?假设我通过将这样一个静态函数(在foo.c中定义)分配给全局函数指针,并在其他文件(bar.c)中调用该函数指针,来编译编译器的愚蠢。显然,我的代码不会给出任何编译警告,但顺便说一句,它给出了分段错误。显然,这是一个保护错误,但我有兴趣知道它是如何在系统内实现的。如何保护静态函数/变量

谢谢。 MS

+3

通过函数指针调用另一个编译单元中的静态函数不应该导致保护错误。发布您的代码。 – 2010-07-08 10:17:30

+0

为什么会有需要愚弄编译器,当它实际上是一种为程序员提供的功能? – 2010-07-08 10:35:27

回答

2

静态的目的不是为了“保护”变量/函数,而是为了保护名称空间,并保护程序的其他部分免受名称冲突符号的干扰。它还允许更多的优化,因为编译器知道它不需要通过外部模块访问符号名称。

5

链接器负责限制函数名称映射到函数的范围。

函数指针调用的静态函数没有保护 - 这并不罕见。例如,推荐的GObject方法的实现方式是公开一个指向静态函数的指针(参见GObject how-to中的虚拟公共方法部分)。

3

它被'保护',仅仅是因为不知道它的符号/位置链接器。所以你不能在另一个模块中写代码,因为链接器没有这样的符号,所以它的符号名称明确地引用了静态对象。没有运行时保护。

如果您在运行时将某个地址传递给某个其他模块的静态对象,那么您将可以通过这样的指针访问它。这不是“编制愚蠢的编译器”(或者实际上是链接器),这样的行为可能是完全合法的。

事实上,你有一个seg-fault可能是一个完全不同的原因(例如一个无效的指针)。编译器可能选择内联代码,在这种情况下指向它的代码将不可行,但是如果你明确地使用了对象的地址,编译器应该实例化它,所以这看起来不太可能。

0

如果将foo.c和bar.c编译为不同的动态加载库,那么您可能会遇到问题。

+0

请详细说明 – 2010-07-08 11:46:45