C++ 对于64位测试(各种平台),是否有编译器标志让malloc返回高于4G限制的指针?

C++ 对于64位测试(各种平台),是否有编译器标志让malloc返回高于4G限制的指针?,c++,testing,64-bit,malloc,C++,Testing,64 Bit,Malloc,我需要测试从32位移植到64位的代码,其中指针被转换为整数句柄,并且我必须确保在64位平台上使用正确大小的类型 各种编译器是否有任何标志,甚至运行时是否有标志可确保malloc返回大于32位限制的指针值 我感兴趣的平台: Windows XP 64和其他64位Windows上的Visual Studio 2008 使用xLC的AIX 64位gcc 使用aCC的64位HP/UX 分配4GB的示例应用程序 因此,多亏R Samuel Klatchko的回答,我能够实现一个简单的测试应用程序,它将尝

我需要测试从32位移植到64位的代码,其中指针被转换为整数句柄,并且我必须确保在64位平台上使用正确大小的类型

各种编译器是否有任何标志,甚至运行时是否有标志可确保
malloc
返回大于32位限制的指针值

我感兴趣的平台:

  • Windows XP 64和其他64位Windows上的Visual Studio 2008
  • 使用xLC的AIX
  • 64位gcc
  • 使用aCC的64位HP/UX

  • 分配4GB的示例应用程序

    因此,多亏R Samuel Klatchko的回答,我能够实现一个简单的测试应用程序,它将尝试在第一个4GB地址空间中分配页面。希望这对其他人和其他用户有用,因此用户可以告诉我它的便携性/有效性

    #include <stdlib.h>
    #include <stdio.h>
    #define UINT_32_MAX 0xFFFFFFFF
    
    #ifdef WIN32
    typedef unsigned __int64 Tuint64;
    #include <windows.h>
    #else
    typedef unsigned long long Tuint64;
    #include <sys/mman.h>
    #include <unistd.h>
    #include <errno.h>
    #include <string.h>
    #endif
    
    static void* Allocate(void* pSuggested, unsigned int PageSize)
    {
    #ifdef WIN32
       void* pAllocated = ::VirtualAlloc(pSuggested, PageSize, MEM_RESERVE ,PAGE_NOACCESS);
       if (pAllocated)
       {
          return pAllocated;
       }
       return (void*)-1;
    #else
       void* pAllocated = ::mmap(pSuggested,
                                 PageSize,
                                 PROT_NONE,
                                 MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, 
                                 -1, 
                                 0);
       if (pAllocated == MAP_FAILED)
       {
          pAllocated = (void*)-1;
       }
       return pAllocated;
    #endif
    }
    
    static void Deallocate(void* pRegion, unsigned int PageSize)
    {
    #ifdef WIN32
       ::VirtualFree(pRegion,0,MEM_RELEASE);
    #else
       ::munmap(pRegion,PageSize);
    #endif
    }
    
    static void Gobble32bitAddressSpace()
    {
    #ifdef WIN32
       SYSTEM_INFO SysInfo;
       ::GetSystemInfo(&SysInfo);
       unsigned int PageSize = SysInfo.dwAllocationGranularity;
    #else
       unsigned int PageSize = ::sysconf(_SC_PAGE_SIZE);
    #endif
    
       unsigned int AllocatedPages = 0;
       unsigned int SkippedPages = 0;
       void *pStart = 0;
       while( ((Tuint64)pStart) < UINT_32_MAX)
       {
          void* pAllocated = Allocate(pStart, PageSize);
          if (pAllocated  != (void*)-1)
          {
             if (pAllocated == pStart)
             {
                //Allocated at expected location
                AllocatedPages++;
             }
             else 
             {
                //Allocated at a different location
                //unallocate and consider this page unreserved
                SkippedPages++;
                Deallocate(pAllocated,PageSize);
             }
          }
          else
          {
             //could not allocate at all
             SkippedPages++;
          }
          pStart = (char*)pStart + PageSize;
       }
       printf("PageSize : %u\n",PageSize);
       printf("Allocated Pages : %u (%u bytes)\n",AllocatedPages,PageSize*AllocatedPages);
       printf("Skipped Pages : %u (%u bytes)\n",SkippedPages,SkippedPages*PageSize);
    }
    
    int main()
    {
       Gobble32bitAddressSpace();
    
       //Try to call malloc now and see if we get an
       //address above 4GB
       void* pFirstMalloc = ::malloc(1024);
       if (((Tuint64)pFirstMalloc) >= UINT_32_MAX)
       {
          printf("OK\n");
       }
       else
       {
          printf("FAIL\n");
       }
       return 0;
    }
    
    #包括
    #包括
    #定义UINT_32_最大0xFFFFFFFF
    #ifdef WIN32
    typedef unsigned_uuint64 Tuint64;
    #包括
    #否则
    typedef无符号长Tuint64;
    #包括
    #包括
    #包括
    #包括
    #恩迪夫
    静态void*Allocate(void*pSuggested,unsigned int PageSize)
    {
    #ifdef WIN32
    void*pAllocated=::VirtualAlloc(pSuggested、PageSize、MEM_RESERVE、PAGE_NOACCESS);
    如果(无效)
    {
    回归苍白;
    }
    返回(无效*)-1;
    #否则
    void*pAllocated=::mmap(pSuggested,
    页面大小,
    普罗图诺,
    MAP|u PRIVATE | MAP|u ANONYMOUS | MAP|u NORESERVE,
    -1, 
    0);
    if(pAllocated==MAP_失败)
    {
    pAllocated=(void*)-1;
    }
    回归苍白;
    #恩迪夫
    }
    静态void解除分配(void*pRegion,unsigned int PageSize)
    {
    #ifdef WIN32
    ::VirtualFree(pRegion、0、MEM_发布);
    #否则
    ::munmap(pRegion,PageSize);
    #恩迪夫
    }
    静态void Gobble32bitAddressSpace()
    {
    #ifdef WIN32
    系统信息系统信息;
    ::GetSystemInfo(&SysInfo);
    unsigned int PageSize=SysInfo.dwAllocationGranularity;
    #否则
    unsigned int PageSize=::sysconf(_SC_PAGE_SIZE);
    #恩迪夫
    unsigned int AllocatedPages=0;
    unsigned int SkippedPages=0;
    void*pStart=0;
    而(((Tuint64)pStart)=UINT\U 32\U最大值)
    {
    printf(“OK\n”);
    }
    其他的
    {
    printf(“失败\n”);
    }
    返回0;
    }
    
    我过去使用过的一种技术是在启动时分配足够的内存,以使低于4GB限制的所有地址空间都用完。虽然这种技术确实依赖malloc首先使用地址空间的较低部分,但在我工作的所有平台(Linux、Solaris和Windows)上都是如此

    由于Linux是如何使用Overmit的,如果您不触及低于4GB限制的分配空间,就不会使用任何虚拟内存


    在Windows上,您可以使用带有MEM_RESERVE标志的VirtualAlloc()来耗尽地址空间,而无需分配任何实际存储。

    您最好重写代码,以便使用intptr_t类型,因为这正是为了使此类实践更安全。不幸的是,它是在c99头文件中定义的,并且VC++不支持c99。但是,这不会阻止您为该平台创建这样的头

    您还可以在发生此类强制转换时添加断言,例如

    assert( sizeof(integer_param) == sizeof(void*) ) ;
    
    或者您可以将值转换回原始指针类型,然后比较:

    assert( (mytype*)integer_param == original_pointer ) ;
    

    不是编译器开关,而是Windows的启动时开关可以执行您想要的操作。有一个名为“nolomem”的命令,它强制将所有内容加载到大于4GB的地址空间中

    如果您使用的是XP,您应该能够在boot.ini中使用/nolomem。请参见OSR上的

    对于Vista/Win7,您可以使用NOLOMEM选项。文件是。可以这样做:

    bcdedit /set {current} NOLOMEM
    

    不是你特别要求的,而是对于其他可能好奇的人来说,Mac OS X上的gcc似乎默认从4GB以上的区域分配64位程序

    下面是一个C程序,用于在任何编译器/操作系统组合上验证这一点:

    #include <stdlib.h>
    #include <stdio.h>
    
    int main() {
        void *p = malloc(1000);
        printf("%p\n", p);
        return 0;
    }
    
    #包括
    #包括
    int main(){
    void*p=malloc(1000);
    printf(“%p\n”,p);
    返回0;
    }
    
    为什么不一开始就分配一次4G呢。只要不写入内存,它就不会从实际物理内存中带走多少,只会占用分页表。你也可以使用一个指向自动(堆栈)变量的指针,它总是远高于4G。所以我尝试了一下……在windows上,我可以建议一个开始指针进行分配,这样我们就可以连续分配地址空间的低端。这在unix上也可行吗?
    mmap
    调用将允许您这样做。使用
    MAP\u ANON
    获取非文件备份内存。