为什么 `_getstream` 会失败?

发布于 2024-07-08 14:54:29 字数 302 浏览 6 评论 0 原文

异常提到

FILE* __cdecl _getstream

我正在调用 fopen 并且它不断崩溃。

AfxMessageBox("getting here 1");
FILE* filePtr = fopen(fileName, "rb");
AfxMessageBox("getting here 2");

由于某种原因,我从来没有进入第二个消息框。 有趣的是,当我处于调试模式时,该应用程序运行良好。 为什么?

The exception mentions

FILE* __cdecl _getstream

I'm calling fopen and it keeps crashing.

AfxMessageBox("getting here 1");
FILE* filePtr = fopen(fileName, "rb");
AfxMessageBox("getting here 2");

For some reason, I never get to the second message box. Interestingly, when I'm in debug mode, the app works perfectly. Why?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

梦回梦里 2024-07-15 14:54:29

我认为内存损坏。 在 Windows 上(__cdecl 让我认为您正在使用它),Windows 调试工具附带了 gflags 实用程序。 有了它,您可以使每个堆分配都有它自己的页面——这将有助于在问题发生时立即捕获内存溢出和双重释放。

我在博客上写了说明:

http://www.atalasoft.com/cs/blogs/loufranco/archive/2007/02/06/6-_2200_Pointers_2200_-on-Debugging-Unmanaged-Code.aspx

有还有其他查找此类错误的技巧。

I think memory corruption. On Windows (which the __cdecl makes me think you are using), there is the gflags utility which comes with the Windows Debugging Tools. With it, you can make each heap allocation have it's own page -- this will help catch memory overruns and double freeing immediately at the point of the problem.

I wrote up instructions on my blog:

http://www.atalasoft.com/cs/blogs/loufranco/archive/2007/02/06/6-_2200_Pointers_2200_-on-Debugging-Unmanaged-Code.aspx

There are other tips for finding this kind of bug there too.

南笙 2024-07-15 14:54:29

我怀疑你的程序的那部分没有任何问题。 最有可能的情况是,您在代码的早期部分出现了某种内存损坏,而这恰好是它出现的地方。

您是否尝试过在调试模式下运行程序的其余部分(在那部分之后)? 如果它是某种内存损坏,那么调试模式分配器应该在释放损坏的内存区域时捕获它,如果不是更早的话。 当然,假设您使用的是带有彻底调试内存分配器的编译器。

I would suspect there's nothing wrong with that part of your program. The most likely scenario is that you've got some kind of memory corruption earlier in the code, and that just happens to be where it shows up.

Have you tried running it through the rest of the program (after that part) in debug mode? If it is some kind of memory corruption, the debug-mode allocator should catch it when it goes to deallocate the corrupted areas of memory, if not sooner. Assuming you're using a compiler with a thorough debugging memory allocator, of course.

咋地 2024-07-15 14:54:29

我怀疑这会影响很多人,因为这是相当晦涩的,但如果你像这样得到 FILE*:

HANDLE hMyFile = CreateFile(...);
FILE* pFile = _fdopen( _open_osfhandle((long)hMyFile, <flags>), "rb" );
CloseHandle(hMyFile);

那么你将泄漏你打开的每个文件的流。 在执行 _open_osfhandle 和 _fdopen 之后,您必须在 pFile 上调用 fclose() 来关闭句柄。 CloseHandle 显然不够聪明,无法释放 fdopen 与您的句柄关联的残骸,但 fclose 足够聪明,可以关闭您的句柄以及与 FILE* 相关的残骸。

我正在开发的应用程序这样做是因为某个 API 传递了 HANDLE,并且该 API 的特定实现者需要 FILE*,因此实现者执行 _fdopen/_open_osfhandle 操作来获取 FILE*。 然而,这意味着调用者的 CloseHandle 调用不足以完全关闭 HANDLE。 修复方法是首先复制传入的 HANDLE,然后 FILE* 代码可以正确地 fclose() FILE* 而不会破坏调用者的 HANDLE。

损坏的程序示例:

#include "stdafx.h"
#include <Windows.h>
#include <io.h>
#include <assert.h>
#include <fcntl.h>
int _tmain(int argc, _TCHAR* argv[])
{

  for(int x = 0;x < 1024; x++)
  {
    HANDLE hFile = CreateFile(L"c:\\temp\\rawdata.txt",GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
    FILE* pFile =  _fdopen( _open_osfhandle((long)hFile, _O_RDONLY | _O_BINARY), "rb" );
    assert(pFile); // this assert will go off at x=509, because _getstream() only has 512 streams, and 3 are reserved for stdin/stdout/stderr
    CloseHandle(hFile);
  }

    return 0;
}

I doubt this will affect many people since this is fairly obscure, but if you get your FILE* like this:

HANDLE hMyFile = CreateFile(...);
FILE* pFile = _fdopen( _open_osfhandle((long)hMyFile, <flags>), "rb" );
CloseHandle(hMyFile);

Then you'll leak a stream for each file you open. After doing _open_osfhandle and _fdopen, you must call fclose() on the pFile to close your handle. CloseHandle is apparently not smart enough to free the cruft that fdopen associates with your handle, but fclose is smart enough to close your handle along with the FILE*-related cruft.

The app I was working on did this because a certain API passed around HANDLEs, and a particular implementor of the API needed a FILE*, so the implementor did the _fdopen/_open_osfhandle stuff to get a FILE*. However, this meant that the caller's CloseHandle call was insufficient to fully close the HANDLE. The fix was to duplicate the incoming HANDLE first, then the FILE* code could properly fclose() the FILE* without breaking the caller's HANDLE.

Sample broken program:

#include "stdafx.h"
#include <Windows.h>
#include <io.h>
#include <assert.h>
#include <fcntl.h>
int _tmain(int argc, _TCHAR* argv[])
{

  for(int x = 0;x < 1024; x++)
  {
    HANDLE hFile = CreateFile(L"c:\\temp\\rawdata.txt",GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
    FILE* pFile =  _fdopen( _open_osfhandle((long)hFile, _O_RDONLY | _O_BINARY), "rb" );
    assert(pFile); // this assert will go off at x=509, because _getstream() only has 512 streams, and 3 are reserved for stdin/stdout/stderr
    CloseHandle(hFile);
  }

    return 0;
}
简美 2024-07-15 14:54:29

我猜想 fileName 有问题(它是否有尾随零?)

尝试注释 fopen 行,看看会发生什么。

I guess that something is wrong with fileName (does it have trailing zero ?)

Try to comment fopen line out and see what will happen.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文