【问题标题】:Why would `_getstream` fail?为什么`_getstream`会失败?
【发布时间】:2008-11-06 02:22:15
【问题描述】:

异常提及

FILE* __cdecl _getstream

我打电话给fopen,它一直在崩溃。

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

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

【问题讨论】:

  • 我几乎怀疑是权限相关的问题。在调试模式下运行意味着提升?什么操作系统和什么开发环境?
  • 邮件顶部的“FILE * __cdecl _getstream”是做什么用的?此外,“rb”不需要括号。

标签: c++ file fopen


【解决方案1】:

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

我在博客上写了说明:

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

还有其他提示可以在那里找到此类错误。

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • 问题是在调试模式下问题不会发生。而且它也只发生在某些文件上,而不是全部。我想你是正确的。我想我要去看看整个过程的内存分配。在发布模式下不容易。
    【解决方案3】:

    我怀疑这会影响很多人,因为这相当模糊,但如果你得到你的 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;
    }
    

    【讨论】:

      【解决方案4】:

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

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

      【讨论】:

        猜你喜欢
        • 2016-04-11
        • 2021-10-10
        • 2013-01-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多