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

par*_*mar 21 c++ dll shared-libraries language-lawyer

C++标准3.6.3规定

静态持续时间的初始化对象的析构函数被调用为从main返回并且由于调用exit而返回的结果

在Windows上你有FreeLibrary和linux你有dlclose来卸载一个动态链接的库.你可以在从main返回之前调用这些函数.

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

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

Dav*_*rtz 23

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

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

dlclose对C++标准中的保证有什么影响,这超出了该标准的范围.没有dlclose什么可以违反C++标准,因为标准没有说明它.

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

  • 这不是标准的运作方式.标准说明会发生什么,但他们绝不会排除你明确要求不同行为的可能性.如果您因明确请求而获得不同的行为,则不会违反该标准.并不要求规则的每个例外都与该规则一起陈述.对于在创建异常的函数的文档中声明规则的例外是完全可以接受和例程的 - 在这种情况下为`dlclose`. (6认同)
  • 是的,它确实.标准明确指出静态析构函数不会在main之前运行,而dlclose会执行它.不是吗? (4认同)
  • 正如我解释的那样,它并没有违反C++标准.C++标准没有说'dlclose`做什么或不做什么.*没有*`dlclose`可能违反C++标准.如果它想,'dlclose`可以使`(1 == 2)`评估为真.这不违反C++标准,因为C++标准没有说'dlclose`应该做什么.标准有一个范围,并且对于范围之外的事情没有*. (3认同)

小智 19

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

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

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

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

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


Ker*_* SB 11

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

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

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

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

  • @parapurarajkumar:对,**如果**库在运行时链接.全局变量和局部静态变量已经非常特殊,并且会导致很多"底层"代码.通过运行时链接,这基本上变成了动态构造(由加载器执行分配和构造). (4认同)

Mar*_*som 2

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

  • 是的,预期的行为是明确的。问题是:“从标准的角度来看会发生什么”,答案是“标准对此没有观点”。 (2认同)