-2

I want to use the windows api call GetWriteWatch(). This method takes an void* array that I allocated on the stack like that: void* lpAddresses[PAGE_COUNT]; The problem now is, that PAGE_COUNT needs to be large and this leads to a stackoverflow. How do I write this to allocate the memory on the heap? I tried:

void* lpAddresses = ::operator new[](PAGE_COUNT); 
void* lpAddresses = ::operator new(PAGE_COUNT); 
void* lpAddresses = malloc(PAGE_COUNT*sizeof(void*));

but that results in an error code from GetWriteWatch()

The version on the stack that works:

ULONG_PTR lpdwCount = PAGE_COUNT;
void *lpAddresses[PAGE_COUNT];
ULONG lpdwGranularity;
UINT result = GetWriteWatch(WRITE_WATCH_FLAG_RESET, m_rawMemory.as_void, m_alloc_size, lpAddresses, &lpdwCount, &lpdwGranularity);

Thanks

simonides
  • 3,040
  • 3
  • 19
  • 34
  • 1
    How do you call `GetWriteWatch` after allocating the array on the heap? Why isn't it included into the question? – AnT stands with Russia Dec 04 '17 at 03:42
  • 2
    `void* lpAddresses[PAGE_COUNT]` is an array of `void*` pointers. The `new[]` equivalent is `void** lpAddresses = new void*[PAGE_COUNT];`, or better `std::vector lpAddresses(PAGE_COUNT);` – Remy Lebeau Dec 04 '17 at 03:43
  • The result from GetWriteWatch != 0. Yep I passed it with the & then. Still no luck. – simonides Dec 04 '17 at 03:44
  • No, no, no! My mistake. If you use the `malloc` version, you will have to pass `(PVOID *) lpAddresses`. Not `&lpAddresses`. Passing `&lpAddresses` is absolutely wrong. – AnT stands with Russia Dec 04 '17 at 03:55
  • @RemyLebeau if you could post that as an answer I'll accept this as the answer. Thank you. Both versions work. – simonides Dec 04 '17 at 10:53

2 Answers2

-1

When you use this function you have to allocate memory using the windows function VirtualAlloc() using the flag MEM_WRITE_WATCH

Something like this:

lpAddress = VirtualAlloc(NULL, PAGE_COUNT, MEM_WRITE_WATCH, PAGE_READWRITE);

https://msdn.microsoft.com/en-us/library/windows/desktop/aa366573(v=vs.85).aspx

  • Why??? `MEM_WRITE_WATCH` is for memory pages to be watched. It has nothing to do with allocation of this array memory at all. That's what your linked page says. – AnT stands with Russia Dec 04 '17 at 03:37
  • Thanks but it is not about the monitored memory. I want to heap allocate the array to pass and recieve the page adresses so my stack won't die. – simonides Dec 04 '17 at 03:40
  • He already said stack memory works fine. So the solution cannot possibly be that he needs VirtualAlloc right??? –  Dec 04 '17 at 03:43
  • @AnT - perhaps you should *read* the linked page. It says: 'This address must be in a memory region that is allocated by the VirtualAlloc function using MEM_WRITE_WATCH.' – bennji_of_the_overflow Dec 04 '17 at 06:17
  • @bennji_of_the_overflow: No, it is you who has to read it more carefully. That remark you quoted applies to `lpBaseAddress`, not to `lpAddresses`. Exactly what I said in my comment above. This question is about allocating memory for `lpAddresses`. – AnT stands with Russia Dec 04 '17 at 06:22
  • @AnT - ah, my apologies - you are 100% correct. I vaguely remembered a similar issue sometime ago and I read the doco too carelessly. – bennji_of_the_overflow Dec 04 '17 at 06:27
-1

The memory allocation itself in your malloc version is perfectly correct. (The ::operator new versions are incorrect.) Just keep in mind that in order to pass a pointer initialized as follows

void* lpAddresses = malloc(PAGE_COUNT*sizeof(void*));
// Assuming `void *` is synonymous with `PVOID`

to GetWriteWatch you will have to cast the pointer to the proper type, i.e. you have to pass (PVOID *) lpAddresses. Passing &lpAddresses instead (which is what you did, according to the comments) is completely and hopelessly incorrect.

If I decided to use malloc in this case I would have done it slightly differently

PVOID *lpAddresses = (PVOID *) malloc(PAGE_COUNT * sizeof *lpAddresses);

i.e. I would perform the cast at the point of memory allocation, and after that passed plain lpAddresses to GetWriteWatch.

Alternatively you can use

PVOID *lpAddresses = new PVOID[PAGE_COUNT];

in which case you will pass plain lpAddresses to the function.

You can also use std::vector or any other memory allocation mechanism. Just keep observing the proper indirection level.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765