繁体   English   中英

Windows Vista + IFileOpenDialog和大堆栈出现内存问题

[英]Windows Vista+ Memory Problem with IFileOpenDialog and large stack

我在Windows Vista及更高版本中遇到了一个奇怪的问题。 当我使用具有大堆栈的IFileOpenDialog时,显示对话框后剩余的内存量减少了大约1 GB。

#include <windows.h>
#include <Shobjidl.h>
#include <iostream>

void memGrab(char *);
int main(int argc, char **argv){
  char Message[128];
  CoInitialize(NULL);
  if(argc > 1){
    wsprintf(Message, "Starting Memory Test: %c", argv[1][0]);
    std::cout << Message << "\n";
    if(argv[1][0] == 'b')
      memGrab("before");
    TCHAR *fileName = (TCHAR *)malloc(sizeof(TCHAR) * 1024);

      IFileOpenDialog *pfd;
    int index = 0;
    int len = 0;
    int i = 0;

    HRESULT hr = CoCreateInstance(CLSID_FileOpenDialog,
            NULL,
            CLSCTX_INPROC_SERVER,
            IID_PPV_ARGS(&pfd));

    if(SUCCEEDED(hr)){
      pfd->Show(NULL);
    }
    pfd->Release();
    if(argv[1][0] == 'a')
      memGrab("After");
  }
  CoUninitialize();
}

void memGrab(char *text){
  for(int i = 0; i < 400000; i++){
    if(!malloc(10240)){
      char Message[128];
      wsprintf(Message, "Memory Gone %s: %d K", text, i * 10);
      std::cout << Message << "\n";
      exit(0);
    }
  }
}

当我在不设置堆栈大小的情况下编译该程序时( cl testMem.cpp Shell32.lib Ole32.lib user32.lib )。 我得到以下结果:

C:\RWSource>testMem.exe b
Starting Memory Test: b
Memory Gone before: 1984040 K

C:\RWSource>testMem.exe a
Starting Memory Test: a
Memory Gone After: 1875640 K

但是,当我通过设置堆栈大小( cl testMem.cpp Shell32.lib Ole32.lib user32.lib /F100000000 )进行编译时。 我失去了大量可分配的内存。

C:\RWSource>testMem.exe b
Starting Memory Test: b
Memory Gone before: 1795370 K

C:\RWSource>testMem.exe a
Starting Memory Test: a
Memory Gone After: 463840 K

更新1:

我用VMMap检查了内存(感谢TheUndeadFish),当我打开对话框时,启动了多个线程,每个线程大约有100MB。 有什么方法可以使主线程具有较大的堆栈,而又不给子线程每个线程100MB?

更新2:

几个月后,我再次回到这个问题。 我将主代码移至另一个函数,并将其作为具有指定堆栈大小的线程启动。 编译时无需堆栈大小。

int main(){
  CreateThread(NULL, 100000000, analyze, NULL, 0, NULL);
  // Wait for analyze thread. 
}

int analyze(int ignore){
  // Do stuff
}

我不知道您的情况到底是怎么回事。 但是我之前已经看到“文件打开”对话框引起了其他内存问题。

调用该对话框时,很多东西可能会加载到您的进程中。 特别是,出现在Windows资源管理器中的Shell扩展也随“文件打开”对话框一起加载。 这样,您便可以在该对话框中右键单击一个文件,并获得所有这些非标准的东西。 但是,这意味着这些扩展的基础dll将被加载到您的进程中。

从经验中,我看到关闭文件打开对话框后,其中一些dll无法卸载。 相反,它们保持当前状态,占用了过程的某些地址空间。 (也许这是这些dll的某种错误,或者也许是某种“优化”以使其保持加载状态,以防再次使用“文件打开对话框”。)

我要处理的结果是,它影响了单个1GB内存分配的成功。 在打开对话框之前,存在大量可用的地址空间,并且可以成功分配1GB。 但是,打开对话框后,几个外壳扩展dll恰好位于可用地址空间的中间,并将其分成小于1GB的块,从而导致分配失败。

我知道这个轶事与您正在做的事情没有直接关系,因为您分配的是很多小额而不是一大笔。 (在我的场景中,没有使用malloc。我认为它类似于VirtualAlloc之类的东西。)但是我猜可能正在发生类似的事情。

“文件打开”对话框可能正在将某些内容加载到您的进程中,从而以某种方式在malloc通常使用的空间中插入了障碍。 但是不知何故,只有在使用较大的堆栈大小时才会发生这种情况,因为我想为堆栈保留的额外99MB空间会以某种方式重新排列其余的地址空间,从而容易受到此问题的影响。

当我调查自己的问题时,我使用VMMap在各个位置拍摄了进程地址空间的快照,以了解正在发生的情况。 您这样做可能会有些运气。 只需注意,它就像操作系统看到的那样看地址空间,而不是真正像您从上下文中看到的特定语言(如C ++)那样。 因此,弄清malloc或任何其他分配机制正在使用内存的哪个特定部分并不一定很容易。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM