WriteProcessMemory doesnt write into Memory - c

i have a problem. I want to write into the Memory of Process so i have programmed the following code. deleteMemoryString() does work normally, but if i pass memory addresses that are longer that 8 characters i wouldnt work. Can i avoid this? Is there specific type i can use or split it into a array?
Thanks
`
[...]
void deleteMemoryString(int pId, DWORD address, int length) {
HANDLE pHandle = OpenProcess(PROCESS_ALL_ACCESS, false, pId);
uint16_t buffer = 0;
for (int i = 0; i < length / 2; i++) {
WriteProcessMemory(pHandle, (LPVOID) address + (i * 2), &buffer, sizeof(buffer), NULL);
}
CloseHandle(pHandle);
}
int main(int argc, char* argv[]) {
deleteMemoryString(getExplorerPID(), 0x7df45c09c0f6, 20);
printf("%x", 0x7df45c09c0f6);
}
`
I excepted that i can write into the memory of a process

Related

How to properly write an array of structs to a pipe in C

I have a hard time figuring out how to pass an array of structs with strings in them through a pipe to a child process.
I created two demos to show my problem.
demo_int.c
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int main()
{
pid_t child;
int pfd[2];
if (pipe(pfd) == -1)
{
exit(1);
}
child = fork();
if (child < 0)
{
exit(1);
}
if (child == 0)
{
close(pfd[1]);
int *arr = malloc(10 * sizeof(int));
if (arr == NULL)
{
exit(1);
}
read(pfd[0], arr, 10 * sizeof(int));
close(pfd[0]);
printf("child process read:\n");
for (int i = 0; i < 10; ++i)
{
printf("%d\n", arr[i]);
}
free(arr);
exit(0);
}
else
{
int *arr = malloc(10 * sizeof(int));
if (arr == NULL)
{
exit(1);
}
for (int i = 0; i < 10; ++i)
{
arr[i] = i;
}
printf("array to be written:\n");
for (int i = 0; i < 10; ++i)
{
printf("%d\n", arr[i]);
}
close(pfd[0]);
write(pfd[1], arr, 10 * sizeof(int));
close(pfd[1]);
free(arr);
printf("parent process done\n");
wait(NULL);
}
}
I created this, so I can be sure that the problem is not with the "dynamic array" part, but with the "structs" part, and maybe more specifically the "string in a struct" part.
This produces the expected result:
array to be written:
0
1
2
3
4
5
6
7
8
9
parent process done
child process read:
0
1
2
3
4
5
6
7
8
9
With valgrind reporting no errors or leaks.
However when I try the same with the problematic structs:
demo_person.c
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
typedef struct Person
{
char *name;
int age;
} Person;
int main()
{
pid_t child;
int pfd[2];
if (pipe(pfd) == -1)
{
exit(1);
}
child = fork();
if (child < 0)
{
exit(1);
}
if (child == 0)
{
close(pfd[1]);
Person *arr = malloc(10 * sizeof(Person));
if (arr == NULL)
{
exit(1);
}
read(pfd[0], arr, 10 * sizeof(Person));
close(pfd[0]);
printf("child process read:\n");
for (int i = 0; i < 10; ++i)
{
printf("%s %d\n", arr[i].name, arr[i].age);
}
for (int i = 0; i < 10; ++i)
{
free(arr[i].name);
}
free(arr);
exit(0);
}
else
{
Person *arr = malloc(10 * sizeof(Person));
if (arr == NULL)
{
exit(1);
}
for (int i = 0; i < 10; ++i)
{
char *name = malloc(8 * sizeof(char));
if (name == NULL)
{
exit(1);
}
sprintf(name, "%s%d", "Person", i);
arr[i].name = malloc(8 * sizeof(char));
if (arr[i].name == NULL)
{
exit(1);
}
strcpy(arr[i].name, name);
arr[i].age = i;
free(name);
}
printf("array to be written:\n");
for (int i = 0; i < 10; ++i)
{
printf("%s %d\n", arr[i].name, arr[i].age);
}
close(pfd[0]);
write(pfd[1], arr, 10 * sizeof(Person));
close(pfd[1]);
for (int i = 0; i < 10; ++i)
{
free(arr[i].name);
}
free(arr);
printf("parent process done\n");
wait(NULL);
}
}
The output is:
array to be written:
Person0 0
Person1 1
Person2 2
Person3 3
Person4 4
Person5 5
Person6 6
Person7 7
Person8 8
Person9 9
parent process done
child process read:
0
1
2
3
4
5
6
7
8
9
free(): invalid pointer
With valgrind reporting loads of errors (as expected after this output).
I found similiar looking questions, but none of the answers seemed to help.
EDIT:
Thanks to the answer I now understand that the problem is with the dynamically allocated string and only the mallocing process can access it, but the real program in which I encountered this problem has been populated (kind of) like this, as in it already uses these dinamically allocated strings.
Is there a way to pass the strings like this, or do I have to solve it somehow with new char[N] arrays?
The memory you allocate with malloc and the pointer it returns are only valid in the process you do the call to malloc.
When you write the structure through the pipe you only write the (current process unique) pointer, not the memory it points to.
The quick and simple solution is to use an actual array instead:
typedef struct Person
{
char name[10];
int age;
} Person;
What you've stumbled upon is commonly solved using what's known as "serialization," which allows you to reliably send and receive data over a wire (pipe, network socket, file, etc). A popular serialization format is JSON, for its wide support and easy readability, but there's nothing stopping you from creating your own serialization format, and just using that!
A common way to pack binary data reliably is to use a header-payload format, where the header contains information about what kind of data is in the payload, and also how long the payload is. From there, it's as simple as reading in a fixed size header, parsing it, then reading the payload on the receiving end.
Something like this may work for you:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
struct simple_header {
char kind; /* I arbitrarily chose a char, which could use something like 's' for string, 'i' for int, etc. Commonly you will see an enum used here */
int length; /* You could use a negative length to indicate errors of some kind, or just use a simple size_t */
};
struct simple_payload {
unsigned char *data;
};
int serialize_string(int fd, const char *payload) {
// Automatically find the size, for convenience
size_t length = strlen(payload);
// Set aside a header and populate it
struct simple_header header;
header.kind = 's';
header.length = (int) length; // This could be checked better, but also just a simple example
// Send the header over the wire, doing minimal error checking
int ret = write(fd, &header, sizeof(header));
if(ret < 0) return ret;
// Send the payload
ret = write(fd, payload, length);
return ret;
}
int deserialize(int fd, struct simple_payload *destination) {
struct simple_header received_header;
int ret = read(fd, &received_header, sizeof(received_header));
if(ret < 0) return ret;
// This solution totally ignores endianness, which you will need to consider if sending and receiving on different computers
// Always work with zeroed buffers when you can, leave room for NULL bytes
destination->data = calloc(received_header.length + 1, 1);
ret = read(fd, destination->data, received_header.length);
if(ret < 0) {
free(destination->data);
return ret;
}
switch(received_header.kind) {
case 's':
/* do something special for strings */
;
default:
return -1; /* unsupported format */
}
return ret;
}
If this is anything more than a pet project, though, I'd recommend looking into serialization formats and their libraries (header-only will be easiest to integrate). With serialization, the devil really is in the details, the unhandled errors and endianness considerations can lead to data corruption, so if you value the data you're sending, please use a library! My included example does not cover:
when the header lies about payload length
payloads that exceed the length of whats in the header
Failed reads/writes, leading you to think you're reading a header when actually you're reading a payload
Error detection/correction (CRC, Reed-Solomon etc)
Struct alignment issues (packed vs unpacked)

Send message through Ring (Circular) Buffer between Threads (in C)

I need to send a message from Main thread to my Created Thread using WinAPI and Ring Buffer.
I defined structures and wrote functions for my Ring buffer.
Ring Buffer - it contains head, tail, size and pointer to the structure Descriptor which has length of Data and data itself. As I need to send 2 parameters to CreateThread function, I created the third structure ThreadParams to keep 2 parameters.
I want to leave this structures how they are now, not changeable.
typedef struct _Descriptor
{
uint32_t dataLen;
void * data;
} Descriptor;
typedef struct _ringBuffer
{
Descriptor *bufferData;
int head;
int tail;
int size;
} ringBuffer;
typedef struct _ThreadParams
{
void * ptr1;
void * ptr2;
} ThreadParams;
There are my realisations of Ring Buffer functions:
void bufferFree(ringBuffer *buffer)
{
free(buffer->bufferData);
}
void ringInitialization(ringBuffer *buffer, int size)
{
buffer->size = size;
buffer->head = 0;
buffer->tail = 0;
buffer->bufferData = (Descriptor*)malloc(sizeof(Descriptor) * size);
}
int pushBack(ringBuffer *buffer, void * data) // fill buffer
{
buffer->bufferData[buffer->tail++] = *(Descriptor*)data;
if (buffer->tail == buffer->size)
{
buffer->tail = 0;
}
return 0;
}
int popFront(ringBuffer *buffer)
{
if (buffer->head != buffer->tail)
{
buffer->head++;
if (buffer->head == buffer->size)
{
buffer->head = 0;
}
}
return 0;
}
My main: I checked that I can send a few bytes (the memory is shared between threads), now I need to send a big message (> BUFF_SIZE) though Ring Buffer what I'm trying to do in while() cycle. Here is the question: how should I do it? My thing doesn't work because I catch an exception in printf() function (memory acces violation).
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <windows.h>
#include <strsafe.h>
#include <stdint.h>
#define RING_SIZE 256
#define BUFFER_SIZE 1024
DWORD WINAPI HandleSendThread(LPVOID params);
uint8_t * getPointer(uint8_t *buffer, uint32_t index)
{
uint8_t * ptr = ((uint8_t*)buffer) + index * BUFFER_SIZE;
return ptr;
}
int main(int argc, char * argv[])
{
//Descriptor * ringData = (Descriptor *)malloc(sizeof(Descriptor) * RING_SIZE);
ringBuffer ring;
ringInitialization(&ring, RING_SIZE);
void * packetBuffer = malloc(BUFFER_SIZE * RING_SIZE);
uint8_t * currentBuffer = getPointer(packetBuffer, 0);
uint8_t * str = "Mr. and Mrs. Dursley, of number four, Privet Drive, were proud to say that they were perfectly normal, thank you very much. They were the last people you'd expect to be involved in anything strange or mysterious, because they just didn't hold with such nonsense. Mr.Dursley was the director of a firm called Grunnings, which made drills.He was a big, beefy man with hardly any neck, although he did have a very large mustache.Mrs.Dursley was thin and blonde and had nearly twice the usual amount of neck, which came in very useful as she spent so much of her time craning over garden fences, spying on the neighbors.The Dursleys had a small son called Dudley and in their opinion there was no finer boy anywhere.";
strcpy(currentBuffer, str);
ring.bufferData[0].data = currentBuffer;
ring.bufferData[0].dataLen = strlen(str);
int currentSize = 0;
int ringSize = RING_SIZE;
while(ring.bufferData[0].data != '\0')
{
for (int i = currentSize; i < ringSize; i + RING_SIZE)
{
pushBack(&ring, currentBuffer);
printf("h = %s, tail = %s, dataBuffer = %s\n", (char*)ring.head, (char*)ring.tail, (char*)ring.bufferData[i].data);
}
currentSize = ringSize;
ringSize = 2 * ringSize;
popFront(&ring);
}
ThreadParams params = { &ring, packetBuffer };
HANDLE MessageThread = 0;
MessageThread = CreateThread(NULL, 0, HandleSendThread, &params, 0, NULL);
if (MessageThread == NULL)
{
ExitProcess(MessageThread);
}
WaitForSingleObject(MessageThread, INFINITE);
CloseHandle(MessageThread);
system("pause");
return 0;
}
And my CreateThread function:
DWORD WINAPI HandleSendThread(LPVOID params)
{
ringBuffer * ring = ((ThreadParams*)params)->ptr1;
void * buffer = ((ThreadParams*)params)->ptr2;
//ring->bufferData[0].dataLen = sizeof(buffer) + sizeof(ring->bufferData[0])*1024;
printf("Shared memory check: ringBuffer data = \"%s\", \nlength = %d\n", (char*)ring->bufferData[0].data, ring->bufferData[0].dataLen);
return 0;
}
Your most immediate problem is the inconsistency between the code in pushBack(), which expects data to point to a Descriptor, and the code in your main function, which passes in a pointer to a string instead.
If you had declared pushBack() properly, i.e.,
void pushBack(ringBuffer *buffer, Descriptor * data)
{
buffer->bufferData[buffer->tail++] = *data;
if (buffer->tail == buffer->size)
{
buffer->tail = 0;
}
}
Then the compiler would have been able to warn you about the discrepancy.
You also have an infinite loop here:
for (int i = currentSize; i < ringSize; i + RING_SIZE)
You probably meant
for (int i = currentSize; i < ringSize; i += RING_SIZE)
... although it still doesn't look to me like it will do anything sensible. Nor do I understand the purpose of the outer loop, which compares a pointer to a character.
Found a solution
int main(int argc, char * argv[])
{
ringBuffer ring;
ringInitialization(&ring, RING_SIZE);
void * packetBuffer = malloc(BUFFER_SIZE * RING_SIZE);
Descriptor temp = { 0 };
uint8_t * currentBuffer = getPointer(packetBuffer, 0);
uint8_t * str = "Mr. and Mrs. Dursley, of number four, Privet Drive, were proud to say that they were perfectly normal, thank you very much. They were the last people you'd expect to be involved in anything strange or mysterious, because they just didn't hold with such nonsense. Mr.Dursley was the director of a firm called Grunnings, which made drills.He was a big, beefy man with hardly any neck, although he did have a very large mustache.Mrs.Dursley was thin and blonde and had nearly twice the usual amount of neck, which came in very useful as she spent so much of her time craning over garden fences, spying on the neighbors.The Dursleys had a small son called Dudley and in their opinion there was no finer boy anywhere.";
strcpy(currentBuffer, str);
temp.dataLen = strlen(str);
temp.data = currentBuffer;
pushBack(&ring, &temp);
ThreadParams params = { &ring, packetBuffer };
HANDLE MessageThread = 0;
MessageThread = CreateThread(NULL, 0, HandleSendThread, &params, 0, NULL);
if (MessageThread == NULL)
{
ExitProcess(MessageThread);
}
WaitForSingleObject(MessageThread, INFINITE);
CloseHandle(MessageThread);
system("pause");
return 0;
}
DWORD WINAPI HandleSendThread(LPVOID params)
{
ringBuffer * ring = ((ThreadParams*)params)->ptr1;
void * buffer = ((ThreadParams*)params)->ptr2;
Descriptor * temp = &ring->bufferData[ring->head];
for (int i = 0; i < temp->dataLen; i++)
{
printf("%c", ((char*)temp->data)[i]);
}
printf("\n");
return 0;
}

How do I properly allocate memory in my C program?

I am writing a Windows program in C for a homework assignment and I am running into a problem that causes my program to crash with program.exe has stopped working. I believe that this is due to the memory not being allocated correctly.
The program is supposed to start multiple threads to perform a task, I have found an example on MSDN on creating threads. I have added parts of the code into my program.
My program:
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <Windows.h>
#define MAX_THREADS 4
#define BUFFER_SIZE 65000
DWORD WINAPI SomeFunction( LPVOID lpParam );
char fileBuffer[BUFFER_SIZE];
typedef struct MyData {
int val1;
int val2;
} MYDATA, *PMYDATA;
int main(int argc, char *argv[])
{
int i = 0;
int j = 0;
PMYDATA pDataArray[MAX_THREADS];
DWORD dwThreadIdArray[MAX_THREADS];
HANDLE hThreadArray[MAX_THREADS];
for (i; i < MAX_THREADS; i++)
{
pDataArray[i] = (PMYDATA) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof(MYDATA));
if( pDataArray[i] == NULL )
{
// If the array allocation fails, the system is out of memory
// so there is no point in trying to print an error message.
// Just terminate execution.
ExitProcess(2);
}
// Create the thread to begin execution on its own.
hThreadArray[i] = CreateThread(NULL, 0, SomeFunction, pDataArray[i], 0, &dwThreadIdArray[i]);
if (hThreadArray[i] == NULL)
{
printf("%s\n", "Error creating thread!");
ExitProcess(3);
}
}
for (j; j < MAX_THREADS; j++)
{
printf("%s%d\n", "j=", j);
WaitForSingleObject(hThreadArray[j], INFINITE);
}
//WaitForMultipleObjects(MAX_THREADS, hThreadArray, TRUE, INFINITE);
i = 0;
for(i; i<MAX_THREADS; i++)
{
CloseHandle(hThreadArray[i]);
if(pDataArray[i] != NULL)
{
HeapFree(GetProcessHeap(), 0, pDataArray[i]);
pDataArray[i] = NULL; // Ensure address is not reused.
}
}
printf("%s\n", "DONE!");
return 0;
}
DWORD WINAPI SomeFunction( LPVOID lpParam)
{
PMYDATA pDataArray;
int anotherInt;
anotherInt = pDataArray->val1; // PROBLEM OCCURS HERE!
printf("%s%d\n", "Printing int ", anotherInt);
return 0;
}
The program above should be able to start multiple threads which execute SomeFunction(). I have isolated bug to this function, specifically the line anotherInt = pDataArray->val1;. pdataArray is an array of MyData defined in a struct and each element is passed into a thread.
Did I not allocate the memory for the array correctly? If not, how would I access the members of the struct that was passed in as the parameter to SomeFunction()? I have gone over my code a couple of times and could not find anything wrong that I know of. The example I followed on MSDN is here.
In MyFunction, PMYDATA pDataArray; doesn't magically become equal to the pDataArray in main. It's an uninitialized pointer, and pDataArray->val1; tries to write to a random memory location.
Hint: you also have a LPVOID lparam which you ignore.

2D global array without knowing lengths. Best practice?

I need to have buffers that I will use it in multiple different types of threads. So the array needs to be global.
Buffer size and number of buffers are given as input to the program.
As an alternative I could implement linked list maybe.
What is the best way to implement such buffers? Can you provide a sample?
Any help is appreciated!
I don't understand what do you mean by "without knowing length", if you pass size of each buffer and number of buffers as input parameters then you know every required length.
Maybe this is not the best, but that would be my way.
First declare global buffer and threads.
static void ** buffer;
pthread_t tid[2];
Here is described how the threads will work. First buffer will assign with data first two sub-buffers. Second will do the same with the other two.
void *assignBuffer(void *threadid) {
pthread_t id = pthread_self();
if (pthread_equal(id, tid[0])) {
strcpy(buffer[0], "foo");
strcpy(buffer[1], "bar");
} else {
strcpy(buffer[2], "oof");
strcpy(buffer[3], "rab");
}
return NULL;
}
Converting program args from string to integer.
Here we assign buffer with arrays of unknown type.
Here we assign each buffer with his size in bytes.
Finally we create working threads. The important thing is that they
will run simultaneously.
Waiting until all threads done their job.
Simple print buffer contents.
Ok, here is the code.
int main(int argc, char **argv) {
//1
int bufferSize = atoi(argv[1]);
int buffersAmount = atoi(argv[2]);
//2
buffer = malloc(sizeof(void *)*buffersAmount);
//3
int i;
for (i = 0; i < buffersAmount; ++i) {
buffer[i] = malloc(bufferSize);
}
//4
i = 0;
while (i < 2) {
pthread_create(&tid[i], NULL, &assignBuffer, NULL);
++i;
}
//5
for (i = 0; i < 2; i++)
pthread_join(tid[i], NULL);
//6
for (i = 0; i < 4; ++i) {
printf("%d %s\n", i, (char*)buffer[i]);
}
for (i = 0; i < buffersAmount; ++i) {
free(buffer[i]);
}
return 0;
}
Feel free to ask if you don't understand something, also sorry for my english it is not my native language.

Producer/consumer with bounded buffer

Could someone check my code and tell me if I am on the right track.. It seems like I am a bit lost.. if you see my errors, please let me know them..
What I am trying to do is to solve bounded buffer using my own semaphores as well as GCD.
Thanks in advance..
sema.c
void procure( Semaphore *semaphore ) {
pthread_mutex_lock(semaphore->mutex1);
while(semaphore->value <= 0)
pthread_cond_wait(&semaphore->condition, semaphore->mutex1);
semaphore->value--;
pthread_mutex_unlock(semaphore->mutex1);
}
void vacate( Semaphore *semaphore ) {
pthread_mutex_lock(semaphore->mutex1);
semaphore->value++;
pthread_cond_signal(&semaphore->condition);
pthread_mutex_unlock(semaphore->mutex1);
}
void init ( Semaphore *semaphore ){
semaphore->value = 1;
pthread_mutex_t myMutex;
semaphore->mutex1 = &myMutex;
pthread_mutex_init( semaphore->mutex1, NULL);
}
void destroy ( Semaphore *semaphore ) {
pthread_mutex_destroy(semaphore->mutex1);
}
and main.c
struct variables {
Semaphore *sem;
};
struct variables vars;
void constructer (int *buffer, int *in, int *out) {
init(vars.sem);
}
void deconstructer () {
destroy(vars.sem);
}
int rand_num_gen() {
uint_fast16_t buffer;
int file;
int *rand;
file = open("/dev/random", O_RDONLY);
while( 1 ) {
read(file, &buffer, sizeof(buffer));
printf("16 bit number: %hu\n", buffer );
*rand = (int) buffer;
close(file);
break;
}
return *rand;
}
void put_buffer( int* buffer, int* in, int* out ) {
buffer[*in] = rand_num_gen(); // produce
procure(vars.sem); // wait here
*in = (*in + 1) % BUF_SIZE;
vacate(vars.sem);
}
void get_buffer( int* buffer, int* in, int* out ) {
int value;
procure(vars.sem);
value = buffer[*out];
vacate(vars.sem);
*out = (*out + 1) % BUF_SIZE;
}
int main (void) {
int *in, *out, *buffer;
constructer(buffer, in, out);
dispatch_queue_t producer, consumer;
producer = dispatch_queue_create("put_buffer", NULL);
consumer = dispatch_queue_create("get_buffer", NULL);
dispatch_async(producer,
^{
int i;
do
{
put_buffer( buffer, in, out );
dispatch_async(consumer,
^{
get_buffer( buffer, in, out );
if (i == RUN_LENGTH) exit(EXIT_SUCCESS);
});
}
while (i < RUN_LENGTH);
});
dispatch_main();
deconstructer();
exit (0);
}
Your code has a bug. In the init function you assign the address of a local variable to semaphore->mutex1, and when the function returns this address will be invalid. Later you still use this address, so this leads to undefined behavior.
You must either allocate the memory for the mutex directly in the semaphore (without a pointer) or allocate the memory via malloc.
Update:
Your program has so many bugs that you should definitely pick an easier topic to learn the basic concepts about memory management, how to allocate, use and reference a buffer, do proper error handling, etc. Here is a slightly edited version of your code. It still won't work, but probably has some ideas that you should follow.
#include <limits.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
void procure(Semaphore *semaphore) {
pthread_mutex_lock(semaphore->mutex1);
while (semaphore->value <= 0)
pthread_cond_wait(&semaphore->condition, semaphore->mutex1);
semaphore->value--;
pthread_mutex_unlock(semaphore->mutex1);
}
void vacate(Semaphore *semaphore) {
pthread_mutex_lock(semaphore->mutex1);
semaphore->value++;
pthread_cond_signal(&semaphore->condition);
pthread_mutex_unlock(semaphore->mutex1);
}
struct variables {
mutex_t sem_mutex;
Semaphore sem;
};
struct variables vars;
void constructor(int *buffer, int *in, int *out) {
vars.sem.value = 1;
vars.sem.mutex1 = &vars.sem_mutex;
pthread_mutex_init(vars.sem.mutex1, NULL);
}
void deconstructor() {
pthread_mutex_destroy(&semaphore->mutex1);
}
int rand_num_gen() {
const char *randomfile = "/dev/random";
unsigned char buffer[2]; // Changed: always treat files as byte sequences.
FILE *f = fopen(randomfile, "rb");
// Changed: using stdio instead of raw POSIX file access,
// since the API is much simpler; you don't have to care
// about interrupting signals or partial reads.
if (f == NULL) { // Added: error handling
fprintf(stderr, "E: cannot open %s\n", randomfile);
exit(EXIT_FAILURE);
}
if (fread(buffer, 1, 2, f) != 2) { // Added: error handling
fprintf(stderr, "E: cannot read from %s\n", randomfile);
exit(EXIT_FAILURE);
}
fclose(f);
int number = (buffer[0] << CHAR_BIT) | buffer[1];
// Changed: be independent of the endianness of the system.
// This doesn't matter for random number generators but is
// still an important coding style.
printf("DEBUG: random number: %x\n", (unsigned int) number);
return number;
}
void put_buffer( int* buffer, int* in, int* out ) {
buffer[*in] = rand_num_gen(); // produce
procure(&vars.sem); // wait here
*in = (*in + 1) % BUF_SIZE;
vacate(&vars.sem);
}
void get_buffer( int* buffer, int* in, int* out ) {
int value;
procure(&vars.sem);
value = buffer[*out];
vacate(&vars.sem);
*out = (*out + 1) % BUF_SIZE;
}
int main (void) {
int inindex = 0, outindex = 0;
int buffer[BUF_SIZE];
constructor(buffer, &inindex, &outindex);
// Changed: provided an actual buffer and actual variables
// for the indices into the buffer.
dispatch_queue_t producer, consumer;
producer = dispatch_queue_create("put_buffer", NULL);
consumer = dispatch_queue_create("get_buffer", NULL);
dispatch_async(producer, ^{
int i;
do {
put_buffer(buffer, &inindex, &outindex);
dispatch_async(consumer, ^{
get_buffer(buffer, &inindex, &outindex);
if (i == RUN_LENGTH) exit(EXIT_SUCCESS);
});
} while (i < RUN_LENGTH);
});
dispatch_main();
deconstructor();
exit (0);
}
As I said, I didn't catch all the bugs.

Resources