2016-08-04 62 views
0

我正在编写一个组件的测试方法,我将一个指针传递给内存中的数据块。 我想把datablob放在更高的地址空间,其中地址比32位宽(我在Windows 7 64位上)。这样我就可以看到组件是否容忍指针地址。 我想测试的组件中有两个功能。一个收到long,另一个收到缓冲地址long long如何把变量放在更高的地址空间(64位)进行测试

foo1(long long ptrBuffer, long size); 
foo2(long ptrBuffer, long size); 

我正在使用visual studio 2013(C++)。有没有办法告诉VS哪里把变量放在内存中?

+0

这不是C++语言标准的一部分,但你可以调整make文件。知道你的动机是什么可能是有用的。如果只是为了验证您的应用程序可以处理高地址,那么在高地址上实际分配变量时模拟该场景可能就足够了。 –

+0

我假设你分配了4GB内存后,任何后续分配将在更高的地址。您可能必须向每个内存页面写入一个字节以标记分配的物理内存。 –

+0

@ PeterA.Schneider:我很确定OP会在事后得到一堆其他问题。为了测试系统的目的,我不太确定这种方法是多么有用。 –

回答

1

这不被C++标准支持。 顺便说一句,如果你想存储指针地址为整数,请使用uintptr_t

uintptr_t已被创建为将指针地址存储为整数句柄。

+0

我对正在测试的组件的接口没有影响。这是一个COM组件dll,并使用'long'和'long long'作为指针地址 – tzippy

4

您可以替换operator new,但这不会影响全局变量或局部变量(即堆栈)。不过,对于测试用例,您可以传递新对象的地址。然后,从操作系统中获取5 GB。至少1GB将会超过4GB,将其用作operator new的备用池。

Win32方法是使用MEM_TOP_DOWN调用VirtualAlloc

+0

我从来没有使用过它,但从文档看来确实是[VirtualAlloc](https://msdn.microsoft.com/en-us/ library/windows/desktop/aa366887(v = vs.85).aspx)是实现它的方法。 –

0

有没有C++的方式来做到这一点,但你可以使用操作系统特定的功能来做到这一点。

对于windows,您可以使用VirtualAlloc()在精确地址处分配(并提交)内存。

2

为了测试是否longlong long实际上足以容纳一个指针,只需添加一个静态断言(C++ 11本已建成,但你也可以自己做一个有#define my_static_assert(x) ((void)sizeof(char[1 - 2*!(x)])))和依赖的功能在这个特别的东西添加

/* function passes a pointer through a long */ 
static_assert(sizeof(long) >= sizeof(uintptr_t)); 

/* function passes a pointer through a long long */ 
static_assert(sizeof(long long) >= sizeof(uintptr_t)); 

这将需要的任何截断问题护理。但是,如果你调用的库对指针值做了一些疯狂的事情,比如掩盖它的某些部分或类似的东西,它并不会帮助你。或者,如果库在内部将指针缩短为针对指针的类型太短。这真的只能经验性地被测试给它高地址。

有关地址空间的一些注意事项:x86_64具有标准化地址的概念,这意味着高位全部相同,并且在物理可寻址区域的大小内复制实际地址的最高位。这是为了确保未来物理地址空间的扩展,一般来说是个好主意。通常地址空间的分区是这样的,即上半部分(0xF ...............)属于内核,下半部分(0x7 ........) .......)是用户空间(对于32位也是如此,只有一半位)。

分配虚拟地址空间所需区域的指针是可能的。在POSIX系统中,mmap系统调用允许您指定一个起始地址作为第一个参数。在Windows中有VirtualAlloc

起始地址必须页面对齐,但这很容易:只要让地址的低20位为0,即使是巨大的页面,它也会如此。堆栈位于用户地址空间的上端(0x7F ..............),然后通常是动态加载的库。程序文本开始waaay下来,随后堆积长大。他们之间有一个很大的空白,可以用mmapVirtualAlloc来填充。所以对于你的测试,我会随机在中间的某个地方随机移动一个测试地址,即0x777777 .... 000000(用随机数填充点)。在一个最小的测试程序中,地址范围应该是未使用的并且试图映射一个内存区域应该可以工作。

相关问题