0

I am trying to populate this entire buffer that I created with the numerical value 9. This buffer is suppose to be 1024 MB

I know I can create the buffer like this.

LPVOID buffer = VirtualAlloc(nullptr,(1 * 1024 * 1024) * 1024, MEM_COMMIT,PAGE_READWRITE);

My question is how can I populate this buffer. Basically what I am looking for is code on how I can iterate over this buffer and insert value into it.

James Franco
  • 4,516
  • 10
  • 38
  • 80
  • Does this answer your question? [c++ - How to use to fill std::array](https://stackoverflow.com/questions/41152968/c-how-to-use-random-to-fill-stdarray) – phuclv Sep 01 '21 at 07:56
  • duplicate for populating with a single byte value: [How to fill array in C++?](https://stackoverflow.com/q/63035170/995714) – phuclv Sep 01 '21 at 07:56
  • Better define it as `LPBYTE`. – i486 Sep 01 '21 at 08:00
  • "Populating a buffer" means, I guess, putting values in the buffer. To answer this question you need to tell us what type are these values and what are the values you want to put. Because of the `1` it looks are size of the type is one, so probably `char`? or your value type has size `1024`? – alfC Sep 01 '21 at 19:04

2 Answers2

1

Standard C Library has also memory functions in the string header file.

#include <string>

memset(buffer, 9, (1 * 1024 * 1024) * 1024));

or just use the for loop and do explicit type casts. You can do everything you want with memory in C++

uint8_t* buffer_as_int = static_cast<uint8_t*>(buffer);
for(size_t i=0,sz=(1024*1024*1024); i<sz; i++) {
   *buffer_as_int = random_byte();
}

You can cast it to whatever type you want, then you change the for loop to an iterator that moves from one pointer to the next

struct Foo { int hello; bool world; };  // 5 bytes aligned to 8 

Foo initial_foo;
initial_foo.hello = 666; 
initial_foo.world = no;

LPVOID end_of_buffer = static_cast<uint8_t*>(buffer) + (1024*1024*1024);
while(buffer < end_of_buffer) {
   *static_cast<Foo*>(buffer) = initial_foo;
   buffer = static_cast<uint8_t*>(buffer) + sizeof(foo);
}

If you understand this example you learned that you can cast everything from and to void easily and do pointer arithmetic on it, because with the addition of a little type checking, a pointer is nothing else than an integer number representing the address of a starting byte in the RAM.

Short, amazing and many say ugly, but C programmers love to do this. And in every heart of a C++ programmer is a little hidden C programmer who want to come out and do dirty things from m time to time.

Lothar
  • 12,537
  • 6
  • 72
  • 121
1

Since the question is tagged C++, here's an important note on filling uninitialized memory. When in need to create objects in a range that was created without calling constructors, you need to use std::uninitialized_fill. This algorithm essentially calls placement new on the "buffer slots" to first enforce a constructor call on the buffer elements. This process is very important in cases where the buffer was created by calling e.g. malloc that is unaware of constructors and performs both steps of constructing and initializing. You can ignore this when initializing trivial types.


When there's a specific value you want to populate with, use std::fill.

std::fill(buffer, buffer + buffer_sz, value);

When in need to create elements according to some policy use std::generate:

std::generate(buffer, buffer + buffer_sz, [] { 
  /* generate some value */ 
} );

Both solutions assume your buffer is strongly typed, i.e. ++buffer will point to the next element in the range. For void* buffers this means you have to cast the iterator to the appropriate type, e.g. :

std::fill(
  static_cast<int*>(buffer), // Creates a strongly typed iterator
  static_cast<int*>(buffer + buffer_size), 
  value); 

That been said, note that for specific uses the standard library offers specialized algorithms, e.g. theres std::iota if you want to fill a range with sequence.

Nikos Athanasiou
  • 29,616
  • 15
  • 87
  • 153