您可以在 Windows 可执行文件中执行逻辑的最后一个位置是什么?
在我的应用程序中,我想在最后一刻执行逻辑。越晚越好。
原因是我跟踪应用程序中的某些元素(数据结构、资源等),并且在应用程序结束时,例程会查看这些元素并报告它们是否未正确关闭、释放、删除、...
到目前为止,我们使用了几种技巧来做到这一点。
第一个技巧是否决 C 运行时的 _heap_term 函数(以及 C 运行时中的一些其他函数)。优点是这工作得很好,但仅限于静态链接 CRT 的应用程序。
第二个技巧是定义一个全局变量,如下所示:
#pragma init_seg(lib)
GlobalApplicationManager s_globalApplicationManager;
pragma 确保此全局变量在所有其他全局变量之前构造,并且 - 更重要的是 - 它在所有其他全局变量之后被破坏。 这样,我们就可以将检查逻辑放在该类的析构函数中。
问题是从 Windows 7 开始,在某些情况下不再调用析构函数。目前尚不清楚是什么影响了这一点,但我们确信如果我们在应用程序中成功建立了 Oracle 连接,则不会调用它。
还有哪些其他技巧可以在应用程序中尽可能晚地执行代码?
In my application, I want to execute logic at the very last moment. The later, the better.
The reason for this is that I keep track of certain elements in my application (data structures, resources, ...), and at the end of the application, a routine looks at these elements and reports if they were not correctly closed, freed, deleted, ...
Until now, we did this using several tricks.
The first trick was to overrule the _heap_term function of the C run time (and some other functions as well in the C Run Time). The advantage was that this worked very well, but was limited to applications in which the CRT was statically linked in.
The second trick was to define a global variable like this:
#pragma init_seg(lib)
GlobalApplicationManager s_globalApplicationManager;
The pragma makes sure that this global variable is constructed before all other global variables, and - more important - that it is destructed after all other global variables.
This way, we can put the checking logic in the destructor of this class.
Problem is that starting from Windows 7 the destructor is not called anymore in some situations. At this moment it is not clear what influences this, but we are sure that it is not called if we make a successful Oracle connection in our application.
What other tricks are there to execute code as late as possible in an application?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
使用
/ENTRYPOINT
。在您的自定义入口点中,调用 CRT 入口点,然后调用您的最终逻辑。Use
/ENTRYPOINT
. In your custom entry point, call the CRT entry point and then your final logic.我认为你应该尝试重构你的代码:
任何成员变量都应该在相关的类析构函数中被析构。
对于全局变量,您可以定义一个销毁函数
void func()
,并在初始化时调用atexit(func)
。I think that you should try to refactor your code:
Any member variable should be destructed in the relevant class destructor.
for global variables, you may define a destruction function
void func()
, and callatexit(func)
upon initialization.CRT 定义了许多部分,您可以使用
#pragma
添加您自己的调用。通过使用正确的名称,您可以在初始化和关闭过程的各个点添加代码。然而,这些名字并不容易找到。查看随 VS2010 安装的 CRT 源中的“crt0dat.c”,了解其中的一些名称。
There are number of sections defined by the CRT to which you can add your own calls with
#pragma
. By using the right name you can add code at various points of the initialisation and shutdown process. However the names are not easy to find.Check out "crt0dat.c" in the CRT source installed with VS2010 for some of the names.
您可以将逻辑放置在辅助 DLL 的
DllMain(DLL_PROCESS_DETACH)
函数中。即使在 EXE 的入口点返回之后也会发生这种情况(假设甚至返回 - 它可能不是由于TerminateThread
),因此它比 Ben Voigt 之前的建议更可靠且更晚。不过,不要以为你能做太多事情。它几乎是您可以执行逻辑的最后一个地方,但您不能再依赖其他 DLL 的存在。这就是 DLL_PROCESS_DETACH 的全部意义。您只能指望剩下的 Kernel32.DLL。
You could place your logic in a
DllMain(DLL_PROCESS_DETACH)
function in a helper DLL. This happens even after the EXE's entry point has returned (assuming that even returns - it might not due toTerminateThread
) so it's more reliable and later than Ben Voigt's earlier suggestion.Don't assume you can do too much, though. It's pretty much the very last place where you can execute logic, but you can't rely on other DLL's being present anymore. That's the entire point of DLL_PROCESS_DETACH. You can only count on Kernel32.DLL being left.
为什么不在调用 ShowWindow 之后向您的窗口/应用程序传递自定义消息?
Why not just pass your window/application a custom message after the call to ShowWindow ?