简体   繁体   中英

How to put variable in higher address space (64bit) for testing

I am wiriting tests for a component where I pass a pointer to a datablob in memory. I want to put the datablob in a higher address space, where the address is wider than 32bit (I'm on Windows 7 64bit). So that I can see whether the component tolerates the pointer address. There's two functions in the component I want to test. One receives a long , the other a long long for the buffer address.

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

I'm working with visual studio 2013 (C++). Is there a way to tell VS where to put a variable in memory?

You can replace operator new , but that won't affect globals or local variables (ie the stack). Still, for a testcase you can pass the address of a new'ed object. Then, grab 5 GB from the OS. At least 1GB of that will be above 4GB, use that as the backing pool for your operator new .

A Win32 approach is to call VirtualAlloc with MEM_TOP_DOWN .

To test if long or long long will actually be sufficient to hold a pointer, just add a static assert (C++11 has this built in, but you can also make one yourself with #define my_static_assert(x) ((void)sizeof(char[1 - 2*!(x)])) ) and in the functions that rely on this particular thing add

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

or

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

That will take care of any truncation issues. It does not help you however, if the library you're calling is doing crazy stuff to the pointer values, like masking some bits of it or similar. Or if the library internally truncates the pointers into types too short for a pointer. That truly can only be tested empirically be feeding it high addresses.

A few notes about address space: x86_64 has the concept of normalized addresses, which means, that the high bits are all identical and copy the highest bit of the actual address within the size of the physically addressable region. That is to ensure future expansion of physical address space and in general is a good idea. The usual partitioning of the address space is so, that the upper half (0xF...............) belongs to the kernel and the lower half (0x7...............) is user space (that's been also the case for 32 bits, just with half the bits).

Allocating pointers from a desired region of virtual address space is possible. In POSIX systems the mmap syscall allows you to specify a starting address as the first parameter. In Windows there's VirtualAlloc

The starting address must be page aligned, but that's rather easy: Just let the lower 20 bits of the address be 0 and even with huge pages it will be so. The stack is located toward the upper end of user address space (0x7F..............) then usually dynamically loaded libraries. Program text starts waaay down followed by the heap growing up. And between them there's a large void that can be filled with mmap or VirtualAlloc . So for your tests I'd go with a test address somewhere in the middle randomly shuffling it around, ie 0x777777....000000 (fill in the dots with random numbers). In a minimal test program that address range should be unused and trying to map a memory region there should work.

That is not supported by the c++ standard. by the way if you want to store pointer address as integer please use uintptr_t .

uintptr_t has been created to store pointer address as integer handle.

there is no C++ way to do this, but you can use OS specific features to do so.

For windows, you can allocate (and commit) memory at a precise address using VirtualAlloc().

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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