I am writing a small program which does all the "write in file" work for the main program. The Data are Structs with not constant sizes. There are plenty of them and new ones are going to be added in the future. Because of that I decided to work with char arrays and hand over the pointer to these arrays from method to method.
70% of the time the code runs as intended, but I frequently get "access violation" errors when the array is written and sometimes this error occurs servel times in a row. I just cant find a pattern.
To note is that Execute runs on an different thread.
struct BufferElement
{
char* ptrData;
int TotalBytes;
int StartPosition;
std::string FileName;
};
class FileThread
{
private:
std::vector<BufferElement> Queue;
bool BoolThread;
std::ofstream writestream;
//This Method calls the "WriteInFile" Method for the first element in the
//Queue and erases it from the vector
void Execute( void )
{
while( BoolThread )
{
if( Queue.size() > 0 )
{
if( WriteInFile() )
{
delete[] Queue.at( 0 ).ptrData;
Queue.erase( Queue.begin() );
}
}
}
}
//This Method writes the first Element of the Queue in the file
bool WriteInFile( void )
{
if( Queue.at(0).ptrData == NULL )
{
return true;
}
writestream.open( Queue.at(0).FileName.c_str(), std::ios::in |
std::ios::out | std::ios::binary );
if( !writestream.is_open() )
{
writestream.close();
writestream.clear();
return false;
}
writestream.seekp( Queue.at( 0 ).StartPosition );
writestream.write( Queue.at( 0 ).ptrData, Queue.at( 0 ).TotalBytes );
writestream.close();
writestream.clear();
return true;
}
public:
void EndThread(void)
{
BoolThread = false;
for( int i = 0; i < Queue.size(); i++ )
{
delete[] Queue.at( i ).ptrData;
}
}
template< typename T >
void WriteOrder( std::string _FileName, T _Data, int _StartPosition )
{
BufferElement Temp_BufferElement;
Temp_BufferElement.TotalBytes = sizeof( _Data );
Temp_BufferElement.StartPosition = _StartPosition;
Temp_BufferElement.FileName = _FileName;
Temp_BufferElement.ptrData = new char[ Temp_BufferElement.TotalBytes ];
memcpy( Temp_BufferElement.DataPtr, _Data, Temp_BufferElement.TotalBytes );
Queue.push_back( Temp_BufferElement );
}
};
int main(void)
{
std::string Path = "..\\Data\\Test.dat";
FileThread Writer;
for( int i = 0; i < 1000; i++ )
{
char array[] = {'H','e','l','l','o',' ','W','o','r','l','d','!','\0'};
Writer.WriteOrder( Path, array, i * sizeof( array );
}
system("pause");
Writer.EndThread();
return 0;
}
I would be glad if someone could take a look over the code. Maybe I just overlook something. I am using Borland Turbo C++ Builder and the Thread is an object from the vcl class.
You need to synchronize the access to the queue. If your main thread writes to the queue while the worker thread is modifying it, you can get a crash. Furthermore, if you do push_back
the array memory might get invalid, while the worker is still working with that invalidated memory.
I also don't see where BoolThread
is initialized or changed. So either this example is incomplete or it might behave strange anyway.