【问题标题】:Is dynamic loading strictly compatible with the C++ Standard?动态加载是否严格兼容 C++ 标准?
【发布时间】:2014-09-21 09:18:38
【问题描述】:

使用动态加载是否需要任何特殊的预防措施才能使代码成为严格合法的 C++?

C++11 标准指的是某些事件的顺序,例如在第一次调用 main() 之前发生的事情。然而,在程序中事件的顺序的典型假设下,动态加载似乎可以摆脱困境。

例如引用 §3.6.2。

静态初始化应在任何动态初始化发生之前进行。

在动态加载的情况下,如果从字面上理解,这似乎是一项几乎不可能的任务。程序可能会导致动态初始化,然后动态加载代码。如果该代码包含通常会被静态初始化的变量,则违反了 C++ 标准。似乎标准规定的事件顺序似乎仍然可以通过“as-if”规则得到满足和合法,但在 SO 的其他地方,其他人警告说不要过于宽泛地解释该规则。

【问题讨论】:

  • 一个正确的程序怎么可能观察到尚未加载的代码中变量的初始化状态?
  • 没错,这就是我提到“as-if”规则的原因。不过,我不是“好像”规则的所有含义的专家。也许还有其他关于动态加载的极端情况。
  • 实际上没有任何回旋的余地来或多或少地解释 as-if 规则,这与其他地方可能建议的相反。静态初始化期间不会发生可观察的事件,因此对象可能在第一次使用之前的任何时间都被静态初始化。
  • 在动态加载发生之前,静态初始化的元素不存在。因此,从原始程序的角度来看,它不是静态初始化的。一旦动态加载开始,该模块[1]的静态初始化将在模块的动态初始化之前发生,并且实际使用该模块的主程序将看不到内容,直到它... [1否,标准不谈论模块,但由于在模块加载之前在模块之外没有任何可见的东西,我们实际上可以将其视为独立的可执行文件,或多或少]。

标签: c++ c++11 language-lawyer dynamic-loading


【解决方案1】:

C++ 标准对动态模块没有任何规定,因此需要进行一定的解释。

是的,动态加载模块中的静态初始化变量将在主模块中动态初始化变量之后进行初始化。您可以观察到这一点,并在它对程序行为产生影响的地方构建程序。但是,如果您将 DLL 视为一个单独的程序,它共享主程序的内存空间但有自己的时间线,您几乎可以在模块级别应用相同的规则,并使用它们来预测应用程序范围内的行为行为。编译器不想让你感到惊讶......它只是有时需要。

顺便说一句,当涉及到 C++ 和 DLL 之间的冲突时,初始化顺序确实是您最不关心的问题。动态模块打破的规则远不止于此,尤其是在 RTTI 方面。

【讨论】:

  • 我真的很喜欢这种对“程序”的巧妙诠释。我认为 C++ 标准说“程序”必须定义一个 main() 函数这一事实会反驳它,但通过动态加载,共享库完全有可能定义一个虚拟 main()。
  • @Praxeolitic 或者,要成为一名真正棘手的语言律师,可以说 DLL 是作为独立实现编译的,因此不需要main()
  • @Sneftel:我认为 DLL 之类的东西是独立实现的主要用例之一,尤其是在允许程序链接到平台提供的 C 版本的非 Unix 环境中库,尽管 C 和 C++ 标准要求的某些功能可能并非在所有此类环境中都受支持。
猜你喜欢
  • 2013-06-18
  • 2014-02-01
  • 1970-01-01
  • 2013-08-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多