文件操作函数返回,但 Windows 关闭时并未实际提交
我正在开发一个 MFC 应用程序,它可以(除其他外)用于关闭 Windows。执行此操作时,Windows 当然会将 WM_QUERYENDSESSION 和 WM_ENDSESSION 发送到所有应用程序,包括我的应用程序。但是,问题是我的应用程序作为某些析构函数的一部分删除了执行期间使用的某些文件(使用 CFile::Remove)。我有理由相信,当 Windows 关闭应用程序时,会调用析构函数(但这很难确定)。
然而,当 Windows 再次启动时,我偶尔会注意到应该删除的文件仍然存在。即使程序的执行相同(我有一个用于测试它的脚本),这种情况也不会始终如一地发生。这让我认为发生了以下两件事之一:要么a)析构函数没有一致地被调用,要么b)Remove函数返回,但在Windows关闭之前文件并未实际删除。
到目前为止我发现的唯一解决方法是,如果我在程序停止后让系统等待大约 10 秒关闭,那么文件将被正确删除。这让我相信 b) 可能是这种情况。
我希望有人能够帮助我解决这个问题。
问候 莫特
I am working on an MFC application that can (among other things) be used to shut Windows down. When doing this, Windows of course sends the WM_QUERYENDSESSION and WM_ENDSESSION to all applications, mine included. However, the problem is that my application, as part of some destructors, delete certain files (with CFile::Remove) that have been used during the execution. I have reason to believe that the destructors are called (but that is hard to know for certain) when the application is closed by Windows.
However, when Windows starts back up again, I do occasionally notice that the files that were supposed to be deleted are still present. This does not happen consistently, even when the execution of the program is identical (I have a script for testing this). This leads me to think that one of two things are happening: Either a) the destructors are not consistently being called, or b) the Remove function returns, but the file is not actually deleted before Windows is shut down.
The only work-around I have found so far is that if I get the system to wait with the shutdown for approximately 10 seconds after my program has stopped, then the files will be properly deleted. This leads me to believe that b) may be the case.
I hope someone is able to help me with this problem.
Regards
Mort
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
一旦您的程序从
WM_ENDSESSION
返回,Windows 就可以随时终止它:如果会话很快结束,那么它可能会在析构函数运行之前结束。您必须在从
WM_ENDSESSION
返回之前完成所有清理工作,因为不能保证您之后有机会执行此操作。Once your program returns from
WM_ENDSESSION
, Windows can terminate it at any time:If the session ends quickly, then it may end before your destructors run. You must do all your cleanup before returning from
WM_ENDSESSION
, because there is no guarantee that you will get a chance to do it afterwards.这里的问题是,某些版本的 Windows 会报告文件处理操作已在实际完成之前完成。这不是问题,除非触发关闭,因为某些操作(包括文件删除)将被放弃。
我建议您通过强制代码等待文件的确认删除(让进程查找文件并在文件消失时引发事件)来解决此问题,然后再调用系统关闭。
The problem here is that some versions of Windows report back that file handling operations have been completed before they actually have. This isn't a problem unless shutdown is triggered as some operations, including file delete will be abandoned.
I would suggest that you cope with this by forcing your code to wait for a confirmed deletion of the files (have a process look for the files and raise an event when they've gone) before calling for system shutdown.
如果系统正确关闭(突然断电等),那么所有缓存的数据都会被刷新。特别是,这包括刷新全局文件描述符表(或文件系统中的任何名称),这应该提交文件删除。
所以问题似乎是用户模式代码没有调用
DeleteFile
,或者它失败了(无论出于何种原因)。请注意,应用程序(进程)可以通过多种方式退出,但并不总是调用 d'tors。有些自动对象在其调用堆栈的上下文中被销毁,另外还有全局/静态对象,它们由 CRT 初始化/清理代码初始化和销毁。
下面是终止进程的方法的简短摘要,其后果是:
ExitThread
退出,要么被TerminateThread
终止。这些线程的自动对象不会被破坏。ExitProcess
退出。自动对象不会被破坏,全局对象可能会被破坏(这种情况发生在 DLL 中使用的 CRT 中)TerminateProcess
终止。所有的d'tors都没有被召唤。我建议您检查是否确实调用了
DeleteFile
(或包裹它的CFile::Remove
),并检查它是否成功。例如,您可能出于某种原因打开同一个文件两次If the system is properly shut down (nut went sudden power loss or etc.) then all the cached data is flushed. In particular this includes flushing the global file descriptor table (or whatever it's called in your file system) which should commit the file deletion.
So the problem seems to be that the user-mode code doesn't call
DeleteFile
, or it failes (for whatever reason).Note that there are several ways the application (process) may exit, whereas not always d'tors are called. There are automatic objects which are destroyed in the context of their callstack, plus there are global/static objects, which are initialized and destroyed by the CRT init/cleanup code.
Below is a short summary of ways to terminate the process, with the consequences:
ExitThread
or killed byTerminateThread
. The automatic objects of those threads are not d'tructed.ExitProcess
. Automatic objects are not destructed, global may be destructed (this happens in the CRT is used in a DLL)TerminateProcess
. All d'tors are not called.I suggest you check if the
DeleteFile
(orCFile::Remove
that wraos it) is called indeed, and check also if it succeeds. For instance you may open the same file twice for whatever reason