动态库是否会破坏 C++标准?
C++ 标准 3.6.3 规定
静态持续时间的初始化对象的析构函数作为从 main 返回的结果和调用 exit 的结果而被调用
在 Windows 上,您有 >FreeLibrary和linux你有dlclose来卸载动态链接库。您可以在从 main 返回之前调用这些函数。
卸载共享库的副作用是运行库中定义的静态对象的所有析构函数。
这是否意味着它违反了 C++ 标准,因为这些析构函数已过早运行?
The C++ standard 3.6.3 states
Destructors for initialized objects of static duration are called as a result of returning from main and as a result of calling exit
On windows you have FreeLibrary and linux you have dlclose to unload a dynamically linked library. And you can call these functions before returning from main.
A side effect of unloading a shared library is that all destructors for static objects defined in the library are run.
Does this mean it violates the C++ standard as these destructors have been run prematurely ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
这是一个毫无意义的问题。 C++ 标准没有说明 dlclose 做什么或应该做什么。
如果该标准包含
dlclose
的规范,那么它肯定会指出dlclose
是 3.6.3 的一个例外。因此,3.6.3 不会被违反,因为它将是一个记录在案的异常。但我们无法知道这一点,因为它没有涵盖它。dlclose
对 C++ 标准中的保证的影响完全超出了该标准的范围。dlclose
所做的任何事情都不会违反 C++ 标准,因为该标准对此没有任何说明。(如果在程序没有执行任何特定操作来调用它的情况下发生这种情况,那么您将有一个合理的理由认为违反了标准。)
It's a meaningless question. The C++ standard doesn't say what
dlclose
does or should do.If the standard were to include a specification for
dlclose
, it would certainly point out thatdlclose
is an exception to 3.6.3. So then 3.6.3 wouldn't be violated because it would be a documented exception. But we can't know that, since it doesn't cover it.What effect
dlclose
has on the guarantees in the C++ standard is simply outside the scope of that standard. Nothingdlclose
can do can violate the C++ standard because the standard says nothing about it.(If this were to happen without the program doing anything specific to invoke it, then you would have a reasonable argument that the standard is being violated.)
Parapura,记住 C++ 标准是一种语言定义,它对编译器如何将源代码转换为目标代码施加限制,这可能会有所帮助。
该标准不对操作系统、硬件或其他任何东西施加限制。
如果用户关闭机器电源,是否违反了 C++ 标准?当然不是。标准是否需要将“除非用户关闭设备电源”作为每条规则的“例外”?那太愚蠢了。
同样,如果操作系统终止进程或强制释放某些系统资源,甚至允许第三方程序破坏您的数据结构,这并不违反 C++ 标准。这很可能是操作系统中的一个错误,但 C++ 语言定义保持不变。
该标准仅对编译器具有约束力,并强制生成的可执行代码具有某些属性。尽管如此,它并不绑定运行时行为,这就是为什么我们在异常处理上花费大量时间的原因。
Parapura, it may be helpful to keep in mind that the C++ standard is a language definition that imposes constraints on how the compiler converts source code into object code.
The standard does not impose constraints on the operating system, hardware, or anything else.
If a user powers off his machine, is that a violation of the C++ standard? Of course not. Does the standard need to say "unless the user powers off the device" as an "exception" to every rule? That would be silly.
Similarly, if an operating system kills a process or forces the freeing of some system resources, or even allows a third party program to clobber your data structures -- this is not a violation of the C++ standard. It may well be a bug in the OS, but the C++ language definition remains intact.
The standard is only binding on compilers, and forces the resulting executable code to have certain properties. Nevertheless, it does not bind runtime behavior, which is why we spend so much time on exception handling.
我认为这是一个开放式问题。
我想说的是这样的:该标准仅定义了程序是什么。程序(我应该添加一个“托管”程序)是一组已编译和链接的翻译单元,它具有唯一的
main
入口点。共享库没有这样的东西,因此它甚至不构成标准意义上的“程序”。它只是一堆链接的可执行代码,没有任何类型的“流程”。如果您使用加载时链接,则库将成为程序的一部分,并且一切都按预期进行。但如果您使用运行时链接,情况就不同了。
因此,您可能喜欢这样看待它:运行时链接共享对象中的全局变量本质上是动态对象,它们由动态加载器构造,并在库卸载时被销毁。这些对象被声明为全局对象的事实并没有改变这一点,因为这些对象当时不是“程序”的一部分。
I'm taking this to be a bit of an open-ended question.
I'd say it's like this: The standard only defines what a program is. And a program (a "hosted" one, I should add) is a collection of compiled and linked translation units that has a unique
main
entry point.A shared library has no such thing, so it doesn't even constitute a "program" in the sense of the standard. It's just a bunch of linked executable code without any sort of "flow". If you use load-time linking, the library becomes part of the program, and all is as expected. But if you use runtime linking, the situation is different.
Therefore, you may like to view it like this: global variables in the runtime-linked shared object are essentially dynamic objects which are constructed by the dynamic loader, and which are destroyed when the library is unloaded. The fact that those objects are declared like global objects doesn't change that, since the objects aren't part of a "program" at that point.
如果您付出巨大努力,它们只会过早运行 - 默认行为是符合标准的。
They are only run prematurely if you go to great effort to do so - the default behavior is standard conforming.
如果确实违反了标准,那么谁是违反者? C++ 编译器不能被视为违规者(因为事物是通过库调用动态加载的);因此它必须是动态加载功能的供应商,也称为操作系统供应商。操作系统供应商在设计系统时是否受到 C++ 标准的约束?这显然超出了标准的范围。
If it does violate the standard, who is the violator? The C++ compiler cannot be considered the violator (since things are being loaded dynamically via a library call); thus it must the the vendor of the dynamic loading functionality, aka the OS vendor. Are OS vendors bound by the C++ standard when designing their systems? That definitely seems to be outside of the scope of the standard.
或者从另一个角度来看,可以将图书馆本身视为提供某种服务的独立程序。当该程序终止时(通过任何方式卸载库),所有关联的服务对象也应该消失,无论静态与否。
Or for another perspective, consider the library itself to be a separate program providing some sort of service. When this program is terminated (by whatever means the library is unloaded) then all associated service objects should disappear as well, static or not.
这只是大量可用的特定于平台的“扩展”(针对目标编译器、体系结构、操作系统等)之一。所有这些都以各种方式“违反”了标准。但偏离标准 C++ 只会带来一个预期的后果:你不再具有可移植性。 (除非您做了很多 #ifdef 或其他操作,但该特定代码仍然被锁定在该平台上)。
由于当前没有标准/跨平台的库概念,因此如果您想要该功能,则必须要么不使用它,要么在每个平台上重新实现它。由于类似的东西出现在大多数平台上,也许有一天标准会找到一种干净的方法来抽象它们,以便标准涵盖它们。优点是跨平台解决方案,并将简化跨平台代码。
This is just one of the tons and tons of platform-specific "extensions" (for a target compiler, architecture, OS, etc) that are available. All of which "violate" the standard in all sorts of ways. But there is only one expected consequence for deviating from standard C++: you aren't portable anymore. (Unless you do a lot of #ifdef or something, but still, that particular code is locked in to that platform).
Since there is currently no standard/cross-platform notion of libraries, if you want the feature, you have to either not use it or re-implement it per-platform. Since similar things are appearing on most platforms, maybe the standard will one day find a clean way to abstract them so that the standard covers them. The advantage will be a cross-platform solution and it will simplify cross platform code.