Im trying to create two threads that simply read and write to files respectively. The reader thread is supposed to read a line from a file, calculate an MD5 value, then write that and some other necessary data to a buffer.
The Writer thread must read the data from the buffer and recalculate the MD5 with the data (which was also passed to the buffer by the reader thread). Then if during the comparison the MD5s are equal, then the writer thread will append that data to a new line in another file.
I have simply implemented a struct buffer to store the necessary values, and pass it on to both threads as pointers to it.
Thing is, to have mutual exclusion, I have/need to implement CritcalSections, everytime something is being read from or written to the buffer.
Just for testing purposes, i wanted to test how is it that the mutually exclude themselves, so I have implemented a small test scenario where one thread writes a value to one of the variables on the buffer, and then the second thread prints it out to the console.
I get the error on the second thread to start right where the EnterCriticalSection(lpCritSec) is.
The error is:
"Exception thrown at 0x7792FE05 (ntdll.dll) in filename.exe: 0xC0000005: Access violation writing location 0x00000004."
I've noticed the writing location address chenges sometimes but I haven't noticed a trend
I've tried testing out different structures, and trying to find any reference errors in the code, but I can't seem to find anything.
#include <stdio.h>
#include <Windows.h>
#include <stdlib.h>
#include <time.h>
/*Data buffer struct*/
typedef struct buffer_data
{
DWORD read_counter;
DWORD wrte_counter;
DWORD run_number;
char* line_data;
char* md5_ctrl;
BOOL read_flag;
} BUFFER_DATA;
typedef struct thread_data
{
BUFFER_DATA* pBuffer;
CRITICAL_SECTION* pCritSec;
} THREAD_DATA;
/*Definition for thread function start address aka callback_function*/
typedef DWORD WINAPI START_ADDR(void*);
/*Predeclaration for functions*/
DWORD WINAPI readerThread(THREAD_DATA thData);
DWORD WINAPI writerThread(THREAD_DATA thData);
HANDLE* init_threads(
BUFFER_DATA* pBuffer,
CRITICAL_SECTION* pCritSec,
START_ADDR* thFunc[]
);
int main(int argc, char* argv[])
{
puts("\nHello Arthur!\n");
puts("Initializing...\n");
/*Vars*/
HANDLE* hThreadsArr;
CRITICAL_SECTION critSec;
START_ADDR* thFunc[] = { readerThread, writerThread };
/*Initializing the data buffer struct*/
BUFFER_DATA buffer_data;
buffer_data.line_data = "";
buffer_data.md5_ctrl = "";
buffer_data.read_counter = 0;
buffer_data.wrte_counter = 0;
buffer_data.read_flag = 0;
buffer_data.run_number = 0;
/*Initialize threads*/
InitializeCriticalSection(&critSec);
hThreadsArr = init_threads(&buffer_data, &critSec, thFunc);
/*TODO something*/
DeleteCriticalSection(&critSec);
return 0;
}
HANDLE* init_threads(
BUFFER_DATA* pBuffer,
CRITICAL_SECTION* pCritSec,
START_ADDR* thFunc[]
)
{
HANDLE* thHandles; //return value of array of thread handles
THREAD_DATA thData; //data to pass to each threa, id est the buffer and the critical section pointer
DWORD idReaderTh, idWriterTh;
//Data for both threads to share
for (int i = 1; i >= 0; i--) {
thData.pBuffer = pBuffer;
thData.pCritSec = pCritSec;
thHandles = (HANDLE*)malloc(sizeof(HANDLE) * 2); //allocating memory for thread handles
thHandles[i] = CreateThread(NULL, 0, thFunc[i], &thData, 0, &idReaderTh); //index 0 = ReaderThread;
if (!thHandles[i])
{
/*printf("Launching Read Thread Error. Exiting. ---ErrNo: %lu\n", GetLastError());*/
fprintf(stderr, "Launching Reader Thread Error. Exiting. ---ErrNo: %lu\n", GetLastError()); //print to stderr dump
return EXIT_FAILURE;
}
printf("Reader Thread Launched Succesfully! TID: %lu\n", idReaderTh);
}
return thHandles;
}
DWORD WINAPI readerThread(void* params)
{
THREAD_DATA thread_data;
thread_data = *(THREAD_DATA*)params;
EnterCriticalSection(thread_data.pCritSec); //this is where i get the error being the code as it is
//thread_data.pBuffer->run_number = 99u;
LeaveCriticalSection(thread_data.pCritSec);
}
DWORD WINAPI writerThread(void* params)
{
THREAD_DATA thread_data;
thread_data = *(THREAD_DATA*)params;
EnterCriticalSection(thread_data.pCritSec);
//thread_data.pBuffer->run_number = 99u;
LeaveCriticalSection(thread_data.pCritSec);
}
Depending on the "for"
loop in the init_threads
method, is how i was changing the order of creation of the threads.
thData
is a local variable that goes out of scope when the init_threads
function returns. This return happens before writerThread
has finished using the data. When it is then accessed by one of your running threads you get Undefined Behavior, which in this case is a crash.
Possible solutions include making thData
static, or using an event so that the threads can signal when they are done using the data. The main thread can then call WaitForMultiple
to wait for both threads to get started.
User contributions licensed under CC BY-SA 3.0