VC的运行时库是有源代码的。例如malloc或者Heap调用的一些地方,能否看出来win的虚拟内存管理是按照什么样的方式划分单位的?谢谢!

解决方案 »

  1.   

    运行库有源代码,但没ntdll.dll的源代码
      

  2.   


    因为我正开始学习用windbg来调试一些windows VC程序遇到的内存问题。
    我想知道VC做内存分配的话,运行时库最终是调用的HeapAlloc对吧,然后在ntdll.dll里面HeapAlloc再去调用VirtualAlloc? 我的说法有问题么?
      

  3.   

    kernel32的HeapAlloc是转向导出ntdll的RtlAllocateHeap
      

  4.   

    还有就是,启动windbg以后,能否知道内存分配的算法把哪些地方做了1k内存列表,哪些做了2k内存列表,哪些做了4k内存列表,等等?
      

  5.   

    SYSTEM_INFO sysInfo = {0};
    GetSystemInfo(&sysInfo);
     //sysInfo.dwPageSize Specifies the page size and the granularity of page protection and commitment. This is the page size used by the VirtualAlloc function. 
      

  6.   


    那也就是说C/C++运行时库的new-->malloc-->HeapAlloc最终都不会调用VirtualAlloc对么? 那么是RtlAllocateHeap去调用的VirtualAlloc么? 我猜不是,因为RtlAllocateHeap是内核函数调用,而VirtualAlloc是用户态函数,不会内核函数还要调用用户态函数的道理。解释一下吧
      

  7.   


    嗯,我的问题在于,VC的C/C++基本运行时库里面的new-->malloc-->HeapAlloc,这个HeapAlloc有没有在内部调用VirtualAlloc,使用new/malloc/HeapAlloc分配的granularity是否也都是64k?
      

  8.   

    ntdll!RtlAllocateHeap是用户模式的,VirtualAlloc是对NtAllocateVirtualMemory的简单封装
    RtlAllocateHeap倒是在NtAllocateVirtualMemory上加了自己的一套算法
      

  9.   


    那么,除了VirtualAlloc是有64k的分配尺度以外,使用new/malloc/HeapAlloc分配的granularity是否也都是64k?有确定的说法么?
      

  10.   


    NtAllocateVirtualMemory()这个是内核态的调用还是用户态的调用?
      

  11.   

    也就是C/C++运行时库最后根本不会调用VirtualAlloc对吧
      

  12.   

    HeapAlloc是先从NtAllocateVirtualMemory获取一大块内存,然后在其上建立自己的数据结构用于更快速的分配,如果预先NtAllocateVirtualMemory得到的够用,就不会调用NtAllocateVirtualMemoryntdll!NtAllocateVirtualMemory是用户模式到ntoskrnl!NtAllocateVirtualMemory的入口
      

  13.   


    谢谢,有个问题,我调试跟踪malloc发现它调用的是_heap_alloc(),这个函数是不是等同于windows api的HeapAlloc呢? 我没有看过内核源代码,还需要大虾你指点一下。我问这个问题是因为我在维护一个windows VC实现的内存池(用于大规模编码/解码的算法),当内存链表需要增长的时候,每次new分配的大小被设定成1k,2k,4k.但是实际运行的过程中这个内存池有好几百M。我觉得反复的分配和释放1k,2k,4k太消耗时间了。然后我看网上说windows 虚拟内存管理的单位是64k,我就想是不是把这个数字设置为64k比较好.但是听你和楼上一位的说法是,这个64k只是VirtualAlloc的设置,对于C/C++运行时库的new-->malloc-->_heap_alloc似乎并不适用啊。
      

  14.   

    继续跟踪_heap_alloc
    HeapAlloc虽然比VirtualAlloc更轻量级,但也是一个通用的算法,并不非常适合一些特定的场合
    如果你只是分配1k,2k,4k的大小,完全可以自己实现一个用slab分配法的内存池,先从VirualAlloc拿一大块(比如几兆),然后在上面建立自己的数据结构
    slab算法专门针对只分配固定几种大小的场合,很快
      

  15.   


    哦,我可能说的不太清楚。我维护的这个内存池,不是用来分配固定大小的对象的。就是用作一个I/O的缓存,当系统负载很高的时候,持续的分配/释放内存来让算法可以有足够的内存可用(同时不浪费)。这种情况下,用new来链接一块块内存做一个内存池是不是有点低效了? 还有就是_heap_alloc我再也跟部进去了,这个提示没有源码啊。
    我用VC10
      

  16.   


    我的程序而已,就是在一直跑的时候,输入模块一直在读入,内存池变大,因为输出模块有很多计算比较慢。这就使得内存池不断的增加1k/2k/4k大小,然后用了一个自己写的算法把这些块连了起来给输出模块的算法用。输出模块处理完再delete。我感觉这种方式效率很低啊,反复的new/delete.所以:
    (1)如果保持这个内存池的链表算法不变的,每次new/delete的大小是多少比较合适?
    (2)有没有更好的内存池实现方法,能动态的变大变小同时效率也比较高的?谢谢.