I have written a C++ Dll which has two functions, one writes a binary file to disk and and other reads that file from disk and load into memory.
//extremely simplified code looks like this
bool Utilities::WriteToBinary(wstring const fileName)
{
//lot of code
DWORD size = //get size of data to write
LPBYTE * blob = new LPBYTE[size];
WriteDataToMemoryBlob(blob, & size);
FILE * pFile;
if(0 != _wfopen_s (&pFile , fileName.c_str() , L"wb" ))
{
//do something
return false;
}
fwrite (blob, 1, size , pFile );
fclose (pFile);
delete[] blob;
return true;
}
bool Utilities::ReadDataFromDisk(wstring const fileName)
{
long fileSize = GetFileSize(fileName);
FILE * filePointer;
if(0 != _wfopen_s (&filePointer, fileName.c_str() , L"rb" ))
return false;
//read from file
LPBYTE * blobRead = new LPBYTE[fileSize];
fread (blobRead, 1, fileSize , filePointer );
fclose (filePointer);
//rest of the code...
Problem
I have created another C++ project which call these DLL methods for testing.
Problem which is driving me crazy is that when I call WriteToBinary and ReadDataFromDisk consecutively inside same program they work perfectly fine. But when I call WriteToBinary at one time and let the program exit and call ReadDataFromDisk next time and give it path of file written earlier by WriteToBinary, I get a BadPtr in blobRead after doing fread.
I have tried my best to make sure there are no shared or static data structures involved. Both methods are totally independent.
Any idea what might be causing this?
A mistake is the allocation of the array as LPBYTE is a BYTE* so the:
LPBYTE * blobRead = new LPBYTE[fileSize];
Is allocating an array of BYTE*, not an array of BYTE. Change to:
BYTE* blobRead = new BYTE[fileSize];
To avoid dynamic allocation you could use a std::vector<BYTE> instead:
std::vector<BYTE> blobRead(fileSize);
Related
I'm having issues with implementing a simple save/load function to a game of chess. The saving appears to work fine as it creates a non-empty file (and doesn't crash the game). The loading, however, always crashes. After trying to debug it a bit it seems to work fine and load the file contents (correctly, after checking the buffer variable), but it crashes when trying to replace the old variables with the loaded ones. I'm trying to replace the current turn with the old turn and the game data (chessboard and the like) to the old game data.
As soon as it tries to execute the last 2 lines of the update function, it crashes the game and gives me an std:bad_alloc crash without further info.
The game itself is a project we need to finish, but this feature wasn't required at all and I just wanted to try and see if I could implement it :). Anyone have a clue as to how to fix it?
This is my save function:
void MainWindow::saveGame(){
saveData saveGameData;
saveGameData.savedGame = g;
saveGameData.savedTurn = turn;
FILE * pFile;
saveData buffer[] = { saveGameData };
pFile = fopen ("save.bin", "wb");
fwrite (buffer , sizeof(saveData), sizeof(buffer), pFile);
fclose (pFile);
}
This is my load function:
void MainWindow::loadGame(){
saveData* tempSaveData;
game tempGame;
zw tempTurn;
FILE * pFile;
long lSize;
saveData * buffer;
size_t result;
pFile = fopen ( "save.bin" , "rb" );
if (pFile==NULL) {fputs ("File error",stderr); exit (1);}
// obtain file size:
fseek (pFile , 0 , SEEK_END);
lSize = ftell (pFile);
rewind (pFile);
// allocate memory to contain the whole file:
buffer = (saveData*) malloc (sizeof(saveData)*lSize);
if (buffer == NULL) {fputs ("Memory error",stderr); exit (2);}
// copy the file into the buffer:
result = fread (buffer,1,lSize,pFile);
if (result != lSize) {fputs ("Reading error",stderr); exit (3);}
// the whole file is now loaded in the memory buffer.
// terminate
fclose (pFile);
free (buffer);
tempSaveData = buffer;
tempGame = tempSaveData->savedGame;
}
This is the saveData struct:
struct saveData {
speelbord savedBord; // speelbord (= chessboard class, in dutch).
zw savedTurn; // black or white enum.
};
Speelbord is a vector< vector < positie > >
positie is a class, one tile on the board being saved as a position.
zw is an enum with white and black as options.
I am working on some software making use of a encryption library, the underlying mechanics of which I can't change. When the program runs it takes about 10 minuets to generate a public and private key, which is extremely frustrating when trying to debug other parts of the software. I would like to write the keys to a file and read them back to save time.
They keys are void pointers:
Enc_Key_T secKey = nullptr;
Where Enc_Key_T is defined as typedef void* Enc_Key_T
The code I have used to attempt to read and write keys is as follows (only attempted to write the secret key so far):
#ifdef WriteKey
generate_Keys(parameters, &sec_key, &prv_key);
FILE * pFile;
pFile = fopen("sk.bin", "wb");
fwrite(&sec_key, sizeof(Enc_Key_T), sizeof(&sec_key), pFile);
fclose(pFile);
#else
FILE * pFile;
long lSize;
char * buffer;
pFile = fopen("sk.bin", "rb");
if(pFile == NULL)
fileError();
fseek (pFile, 0 , SEEK_END);
lsize = ftell (pFile);
rewind (pFile);
buffer = (char *) malloc (sizeof(char)*lSize);
if(buffer == NULL)
memError();
sec_key = (void *) fread(buffer, 1, lSize, pFile);
fclose(pFile);
free(buffer);
#endif
When I write the file it comes out as 64 byte file, but reading it back in the secret key pointer gets set to a low value memory address, which makes me think I am doing something wrong. I can't find any examples of how this can be done. I'm not even sure it can, as I won't be creating any of the underling structures, so I am just trying to allocate some memory at a location provided by a pointer.
Is there anyway this can be done without having to touch the underlying library that generates the keys?
Short answer: in general, you cannot do that correctly.
Long answer:
The thing that you're missing is the structure, you have no guarantee that Enc_Key_T can be serialized by simply writing memory contents. In addition, even if it just raw random data, there is no known length of it.
In addition, there is no guarantee that the library does not have its own state, bound to the generated keys.
Code issues:
When writing, you have no known length of data. Data that is written is a pointer and then something bogus.
When reading, you don't need a secondary buffer; besides, fread returns number of bytes read, not a pointer to the data. So instead of:
buffer = (char *) malloc (sizeof(char)*lSize);
if(buffer == NULL)
memError();
sec_key = (void *) fread(buffer, 1, lSize, pFile);
you can write:
sec_key = (void *) malloc (lSize);
if(sec_key == NULL)
memError();
if ( 0 == fread(sec_key, 1, lSize, pFile) ) {
// error
}
I will assume you are going to debug intensively this application such that you may invest 1 hour building those wrappers I am suggesting.
As you long as you do not know the underlying structure and this library is a black box you have to do the following:
void generate_KeysEx(...){
#if DEBUG
// return dummy keys
#else
// call this API
#endif
}
void EncryptEx(...){
#if DEBUG
// return cipher same as plain text
#else
// call this library API
#endif
}
From discussions in the comments it doesn't sound like this is possible without capturing the structure in the library, which would require significant code changes.
A very hacky solution I found was to change a few key generation parameters which drastically reduces run time.
I need to create a custom reading callback function that can read contents of a file in the form of a std::string into a uint8_t * buf. I tried multiple different methods found around the internet and on stackoverflow but sometimes it works and other the the program infinitely loops or stops execution half way.
I have no problems with amr/3gp files but all wav/pcm files are causing some problems for some reason. All I know its something to do with the reading function I have so far.
Ideally I would like to be able to give the program any type of file and then it converts it.
This is how I am calling the readCallback function from the code:
//create the buffer
uint8_t * avio_ctx_buffer = NULL;
//allocate space for the buffer using ffmpeg allocation method
avio_ctx_buffer = (uint8_t *) av_malloc(avio_ctx_buffer_size);
//Allocate and initialize an AVIOContext for buffered I/O.
//audio variable contains the contents of the audio file
avio_ctx = avio_alloc_context(avio_ctx_buffer, avio_ctx_buffer_size,0, &audio, &readCallback, NULL, NULL);
Here is the callback function that works on some types of files:
static int readCallback(void* opaque, uint8_t * buf, int buf_size){
std::string * file =static_cast<std::string *>(opaque);
if(file->length() == 0){
return AVERROR_EOF; //if we reach to the end of the string, return
// return End of file
}
// Creating a vector of the string size
std::vector<uint8_t> array(file->length());
//Copying the contents of the string into the vector
std::copy(file->begin(),file->end(),array.begin());
//Copying the vector into buf
std::copy(array.begin(),array.end(),buf);
return file->length();
}
After tyring some stuff for awhile, I got a solution using std::stringstream and it works well with several formats I tested with so far: 3gp/amr,wav/pcm,mp3.
Here a the snippet of code:
//Create a string stream that contains the audio
std::stringstream audio_stream(audio);
//create the buffer
uint8_t * avio_ctx_buffer = NULL;
//allocate space for the buffer using ffmpeg allocation method
avio_ctx_buffer = (uint8_t *) av_malloc(avio_ctx_buffer_size);
//Allocate and initialize an AVIOContext for buffered I/O.
//Pass the stringstream audio_stream
avio_ctx = avio_alloc_context(avio_ctx_buffer, avio_ctx_buffer_size,0,&audio_stream, &readCallback, NULL, NULL);
The callback function:
static int readFunction1(void* opaque, uint8_t * buf, int buf_size){
//Cast the opaque pointer to std::stringstream
std::stringstream * me =static_cast<std::stringstream *>(opaque);
//If we are at the end of the stream return FFmpeg's EOF
if(me->tellg() == buf_size){
return AVERROR_EOF;
}
// Read the stream into the buf and cast it to char *
me->read((char*)buf, buf_size);
//return how many characters extracted
return me->tellg();
}
I'm trying to read a jpg file from disk, and copy to a char buffer. The problem is that on the bytes there are some NULL character, and I'm having problems when I read the char buffer.
This is the current code:
char* readImg(char* filename)
{
FILE * pFile;
char jpgBuffer[20048];
long lSize;
errno_t result = fopen_s (&pFile,filename,"rb");
if (result != 0) {
printf("Error \n");
}
fseek (pFile , 0 , SEEK_END);
lSize = ftell (pFile);
rewind (pFile);
result = fread (jpgBuffer,1,lSize,pFile);
fclose (pFile);
jpgBuffer[lSize] = '\0';
return jpgBuffer;
}
and the call to the function is:
char* img = readImg("img.jpg");
then, I need to encode into base64, but if I want to know the size of the image buffer with strlen(), I'm getting a size of 4, because the 5 character is a "0".
How can I avoid the NULL characters into image buffer?
You may change your function prototype.
long readImage(const char* filename, char* buf, long bufSize)
{
FILE * pFile;
long lSize;
errno_t result = fopen_s (&pFile,filename,"rb");
if (result != 0) {
printf("Error \n");
}
fseek (pFile , 0 , SEEK_END);
lSize = ftell (pFile);
rewind (pFile);
if(bufSize < lSize)
{
printf("buf too small, needs %lu\n", lSize);
fclose(pFile);
return -1;
}
result = fread (buf,1,lSize,pFile);
fclose (pFile);
return lSize;
}
Then you get img data & actual size of it.
If you don't mind using malloc, you can alloc memory for buffer in your function.
long readImage(const char* filename, char** pbuf)
{
FILE * pFile;
long lSize;
errno_t result = fopen_s (&pFile,filename,"rb");
if (result != 0) {
printf("Error \n");
}
fseek (pFile , 0 , SEEK_END);
lSize = ftell (pFile);
rewind (pFile);
*pbuf = (char*)malloc(lSize * sizeof(char));
result = fread (*buf,1,lSize,pFile);
fclose (pFile);
return lSize;
}
call this function like following, and you need to remember free buffer.
char* buf = NULL;
long len = 0;
len = readImage(filename, &buf);
...
free(buf);
Use the lSize you determine in readImg(...) as the file size. strlen is for null terminated strings. dont use strlen to determine image size in bytes.
Note also, that you should assign jpgBuffer as a heap variable via new[] using lSize as the byte size. That way you can return a pointer to heap memory. Your current stack variable jpgBuffer will be invalid after the function returns, and hence the pointer to it. This way you also dont have to worry about the situation where you need more bytes than your hardcoded value (which you currently dont check!).
You will also want to return the lSize via an input parameter pointer/ref variable so you have a bounds to iterate over later on.
You can't use strlen to something that is not a string. You should return the size from the readIamge function. e.g.
char* readImg(char* filename, int *size);
If you program in C++ your should instead return an instance of a kind of an image class. This would avoid the splattered location of results.
Further you should never return the address of a local variable as your jpgBuffer. This variable will be overwritten aftern return from function.
You can return your data as a char* without any size information.
You can't return your jpgBuffer, locally allocated.
Change your function into:
int readImg(char* filename, unsigned char* buffer)
{
//...
result = fread (buffer,1,lSize,pFile);
return lSize;
}
If you can, allocate your buffer in the calling function, it will simplify your code.
However, it you want to avoid buffer overflow, you should pass the size of the allocated buffer to your read function, and return an error/throw an exception if the file size is greater than the size you allocated.
int readImg(char* filename, unsigned char* buffer, size_t aSize)
{
//...
fseek (pFile , 0 , SEEK_END);
lSize = ftell (pFile);
if (lSize > aSize)
{
// Manage error case
}
//...
result = fread (buffer,1,lSize,pFile);
return lSize;
}
Keep in mind that this way of coding is more C-style than C++-style. If you wish and can use C++, take advantage of C++ constructs, standard library to improve your code.
jpgBuffer is a "binary" buffer, not a "string". Put a null char at the end is non-sense. You should use the result variable to read your buffer.
I have this theory, I can grab the file size using fseek and ftell and build a dynamic array as a buffer. Then use the buffer for fgets(). I currently can not come up with a way to do it.
My theory is based off of not knowing the size of the first file in bytes. So, I do not know how big of a buffer to build. What if the file is over 2 gigs? I want to be able to build a buffer that will change and recognize the file size of whatever file I put into SearchInFile().
Here is what I have so far below:
int SearchInFile(char *fname, char *fname2)
{
FILE *pFile, *pFile2;
int szFile, szFile2;
// Open first file
if( (fopen_s(&pFile, fname, "r")) != NULL )
{
return(-1);
}
// Open second file
if( (fopen_s(&pFile2, fname2, "r")) != NULL )
{
return(-1);
}
// Find file size
fseek(pFile, 0L, SEEK_END);
szFile = ftell(pFile);
// Readjust File Pointer
fseek(pFile, 0L, SEEK_SET);
std::vector <char> buff;
//char buff[szFile];
while(fgets(buff.push_back(), szFile, pFile))
{
}
Any thoughts or examples would be great. I've been searching the net for the last few hours.
Vector can grow, so you don't have to know the size beforehand. The following four lines do what you want.
std::vector<char> buff;
int ch;
while ((ch = fgetc(pFile)) != EOF)
buff.push_back(ch);
fgetc is a function to read a single char, simpler than using fgets.
If you do know the file size beforehand then you could call buff.reserve(szFile) before the loop. This will make the loop a little more efficient.