Fill Memory with Random Data

Populate a region of memory with random data

RAND_MAX is guaranteed to be at least 215−1 so there is no problem filling an entire byte with randomness with a single call to rand(), unless your architecture has bytes larger than 15 bits (in which case your hard-coded multiplication by 8 will also be problematic).

Doing the generation byte by byte is straight-forward and requires no bit-hacking cleverness.

Personally, I wouldn't worry about "wasting bits" from a call to rand(); the bits produced by that standard library function aren't worth much on most implementations. The real problem is to decide which bits to throw away so that the remaining ones are reasonably well-distributed. If possible, to cope with the range of inferior PRNGs generally used, you should go for the middle bits.

A better solution might be to simply provide your own PRNG; portable source code implementations exist, and some are well studied.

fill memory with random data

Linux provides you with /proc/pid/maps and /proc/pid/mem, for your own pleasure. Of course you have to be extra careful when writing there. Also, keep in mind the only memory segment available to each process is its own, so you'll probably have to do some attaching and code patching to get where you want. Good luck, anyways. :)

edit: It's still quite a few times more complicated than a code audit - which also has greater chances to reveal the actual source of the problem.

Filling memory with random bytes - C/Objective-C

You can use arc4random_buf to fill the buffer with random data:

#include <stdlib.h>
#include <stdint.h>

uint8_t iv[kCCBlockSizeAES128];
arc4random_buf(&iv, kCCBlockSizeAES128);

Also, the memory block returned by malloc (as with any uninitialised memory) is filled with garbage. You should not assume that it will be filled with anything, especially not cryptographically useful random numbers.

Create buffer and fill it with random numbers

You need

malloc (size*sizeof(int))

instead of

malloc (size*sizeof(uint8_t))

or maybe you need

uint8_t* buffer = malloc (size*sizeof(uint8_t));

It depends if you want a buffer of 10 int of a buffer of 10 uint8_t.

For printing the content of the buffer use:

for (i = 0; i < size; i++)
{
printf("%d\n", buffer[i]) ;
}

Following line only prints the address of the buffer.

printf("Content of buffer = %d\n", buffer);

Filling an array with random numbers in a range in C

Georgi.

I've made a successfull test with the following code.
I think the problem could be a several things, but mainly allocating memory locally instead globally.
If this won't help you, I suggest you put here the complete code for your attempt application.

:)

void randomgen(int *intarray, int size, int max, int min)
{
int i;

for (i = 0; i < size; i++) {
intarray[i] = (rand() % (max - min + 1)) + min;
printf("%d ", intarray[i]);
}
}
int main(int argc, char **argv){
int *iA;
int i;

if ( (iA = (int*)malloc(20 * sizeof(int))) == NULL ){
printf("error");
return 0;
}
randomgen(iA, 20, 59, 50);

for (i = 0; i < 20; i++) {
printf("iA[%d]=%d\n", i, iA[i]);
}
return 0;
}

It produces the following output:

53 56 57 55 53 55 56 52 59 51 52 57 50 59 53 56 50 56 52 56
iA[0]=53
iA[1]=56
iA[2]=57
iA[3]=55
iA[4]=53
iA[5]=55
iA[6]=56
iA[7]=52
iA[8]=59
iA[9]=51
iA[10]=52
iA[11]=57
iA[12]=50
iA[13]=59
iA[14]=53
iA[15]=56
iA[16]=50
iA[17]=56
iA[18]=52
iA[19]=56

Fill huge file with random data quickly

Your limiting factor is probably the speed of your hard disk. Nevertheless you may gain some performance by splitting the work in two. One thread (the producer) will produce the random lines, and another thread (the consumer) will write the produced lines in the file. The code bellow writes 1,000,000 random lines to a file in my SSD in less than a second (10 MB).

BlockingCollection<string> buffer = new(boundedCapacity: 10);
Task producer = Task.Factory.StartNew(() =>
{
Random random = new();
StringBuilder sb = new();
for (int i = 0; i < 10000; i++) // 10,000 chunks
{
sb.Clear();
for (int j = 0; j < 100; j++) // 100 lines each chunk
{
sb.AppendLine(random.Next().ToString());
}
buffer.Add(sb.ToString());
}
buffer.CompleteAdding();
}, default, TaskCreationOptions.LongRunning, TaskScheduler.Default);
Task consumer = Task.Factory.StartNew(() =>
{
using StreamWriter outputFile = new(@".\..\..\Huge.txt");
foreach (string chunk in buffer.GetConsumingEnumerable())
{
outputFile.Write(chunk);
}
}, default, TaskCreationOptions.LongRunning, TaskScheduler.Default);
Task.WaitAll(producer, consumer);

This way you don't even need thread safety in the production of the random lines, because the production happens on a single thread.


Update: In case the writing to disk is not the bottleneck, and the producer is slower than the consumer, more producers can be added. Below is a version with three producers and one consumer.

BlockingCollection<string> buffer = new(boundedCapacity: 10);
Task[] producers = Enumerable.Range(0, 3)
.Select(n => Task.Factory.StartNew(() =>
{
Random random = new(n); // Non-random seed, same data on every run
StringBuilder sb = new();
for (int i = 0; i < 10000; i++)
{
sb.Clear();
for (int j = 0; j < 100; j++)
{
sb.AppendLine(random.Next().ToString());
}
buffer.Add(sb.ToString());
}
}, default, TaskCreationOptions.LongRunning, TaskScheduler.Default))
.ToArray();
Task allProducers = Task.WhenAll(producers).ContinueWith(_ =>
{
buffer.CompleteAdding();
}, TaskScheduler.Default);
// Consumer the same as previously (omitted)
Task.WaitAll(allProducers, consumer);

How to initialize a struct with random data in C?

Okay, I actually found the answer to my own question. The main problem is that there isn't an initializer for my struct. However, there already exist serialization functions. So we can use the non-working second solution, and convert it to a working solution.

So a much cleaner solution would be:

myStruct testData = {0};
myStruct readData = {0};
uint8_t* randomData = genRandomData(sizeof(myStruct));
memcpy(&testData, randomData, sizeof(myStruct));
save(&testData);
load(&readData); // readData is now a valid random struct.

myStruct realReadData = {0}
save(&readData);
load(&realReadData);

memcmp(readReadData, readData, sizeof(myStruct)); // This does equal 0 if serialize/deserialize functions are correct.

If there's an issue in serialize/deserialize functions, the input struct (corrupt as it may be) should provide different results.



Related Topics



Leave a reply



Submit