动态库是否打破了C ++标准?

时间:2011-11-03 22:24:51

标签: c++ dll shared-libraries language-lawyer

C ++标准 3.6.3 陈述

静态持续时间的初始化对象的析构函数是从main返回的结果和调用exit的结果调用的

在Windows上,您拥有 FreeLibrary ,而您拥有 dlclose 的Linux可以卸载动态链接的库。你可以在从main返回之前调用这些函数。

卸载共享库的副作用是运行库中定义的静态对象的所有析构函数。

这是否意味着它违反了C ++标准,因为这些析构函数已经过早运行了?

7 个答案:

答案 0 :(得分:23)

这是一个毫无意义的问题。 C ++标准没有说明dlclose做了什么或应该做什么。

如果标准要包含dlclose的规范,那么肯定会指出dlclose是3.6.3的例外。因此,3.6.3不会被违反,因为它将是一个记录在案的例外。但我们无法知道,因为它没有涵盖它。

dlclose对C ++标准中的保证有什么影响,这超出了该标准的范围。 dlclose可以做的任何事情都不能违反C ++标准,因为标准没有提及它。

(如果没有程序执行任何特定的调用就会发生这种情况,那么你就会有一个合理的论据,即违反了标准。)

答案 1 :(得分:19)

Parapura,请记住,C ++标准是一种语言定义,对编译器如何将源代码转换为目标代码施加约束可能会有所帮助。

该标准不对操作系统,硬件或其他任何内容施加约束。

如果用户关闭了他的计算机,是否违反了C ++标准?当然不是。标准是否需要说“除非用户关闭设备”作为每个规则的“例外”?那太傻了。

同样,如果操作系统杀死进程或强制释放某些系统资源,甚至允许第三方程序破坏您的数据结构 - 这不违反C ++标准。它可能是操作系统中的一个错误,但C ++语言定义仍然完好无损。

标准仅对编译器具有约束力,并强制生成的可执行代码具有某些属性。然而,它并没有绑定运行时行为,这就是我们在异常处理上花费这么多时间的原因。

答案 2 :(得分:11)

我认为这是一个开放式的问题。

我会说是这样的:标准只定义了程序是什么。一个程序(一个“托管”的程序,我应该添加)是一个编译和链接的翻译单元的集合,它具有唯一的main入口点。

共享库没有这样的东西,所以它甚至不构成标准意义上的“程序”。它只是一堆链接的可执行代码,没有任何“流”。如果使用加载时链接,则库将成为程序的一部分,并且所有内容都符合预期。但是如果使用运行时链接,则情况会有所不同。

因此,您可能希望像这样查看:运行时链接共享对象中的全局变量本质上是动态对象,它由动态加载器构造,并在卸载库时被销毁。这些对象被声明为全局对象的事实并没有改变这一点,因为那时对象不是“程序”的一部分。

答案 3 :(得分:2)

如果您付出了巨大努力,它们只会过早运行 - 默认行为是符合标准的。

答案 4 :(得分:1)

如果它违反了标准,谁是违规者? C ++编译器不能被视为违规者(因为事物是通过库调用动态加载的);因此它必须是动态加载功能的供应商,也就是OS供应商。在设计系统时,OS供应商是否受C ++标准的约束?这似乎超出了标准的范围。

答案 5 :(得分:1)

或者从另一个角度来看,将库本身视为一个提供某种服务的独立程序。当该程序终止时(通过无论何种方式卸载库),所有相关的服务对象也应该消失,静态或不静止。

答案 6 :(得分:0)

这只是可用的大量平台特定“扩展”(针对目标编译器,体系结构,操作系统等)中的一种。所有这些都以各种方式“违反”标准。但是偏离标准C ++只有一个预期结果:你不再可移植了。 (除非你做了很多#ifdef或者其他什么,但是,特定的代码仍被锁定在那个平台上)。

由于目前没有标准/跨平台的库概念,如果您需要该功能,则必须不使用它或者按平台重新实现它。由于类似的东西出现在大多数平台上,也许标准有一天会找到一种简洁的方式来抽象它们,以便标准涵盖它们。优势将是跨平台解决方案,它将简化跨平台代码。