Deleting memory buffer crashes program and other strangeness Topic is solved

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
TexasJimbo
Knows some wx things
Knows some wx things
Posts: 28
Joined: Sun May 04, 2008 6:41 pm

Deleting memory buffer crashes program and other strangeness

Post by TexasJimbo » Sun Jan 29, 2012 9:58 pm

I am trying to allocate a buffer for binary data, retrieve the binary data from an SQLite database, create a file to hold the data and write it to disk then close the file and delete the buffer. I am running into two different problems. 1) When I try to delete the buffer, the program crashes... and 2) If I don't delete the buffer and do successfully create the file, I cannot access it when I return from the function call. The code that calls the routine attempts to open the file when it returns and I get a message 'Can't open file <whatever the file name is' (error 5: access is denied). I am trying to get around the apparent hold on the file by creating (opening and closing) a dummy file immediately after I create the real one....don't really know if this works yet, but am interested to know if anyone has experienced the kind of problem I am describing with this - and if you found a way around it....btw, my platform is Windows.

Here is the code snippet where I am trying to create this binary file.

Code: Select all

//=============================================================
// GetAlphaElementsSoundFile   ***(uses ppStmt2 and pzTail2)***
//=============================================================
int SQLiteDB::GetAlphaElementsSoundFile( wxString soundFileName, wxString fileToCreate, wxString dummyFile )
{
   bool soundFileExists = false;
   long int bytesWrote = 0;
wxString tBuf;

   tempBuff.sprintf(wxT("SELECT SOUNDFILESIZE FROM ALPHAELEMENTS WHERE SOUNDFILENAME = '%s'"), soundFileName.GetData());

   // Part 1, get the soundfile size.
   retCode = sqlite3_prepare_v2(db, tempBuff.utf8_str(), -1, &ppStmt2, &pzTail2);
   if (retCode == SQLITE_OK) 
      mLog -> WriteToLog(wxT("GetAlphaElementsSoundFile Prepare size statement OK"));
   else {
      tempBuff.sprintf(wxT("GetAlphaElementsSoundFile Prepare size statement Failed...error code: %d"), retCode);
      mLog -> WriteToLog(tempBuff);
   } // end else

   retCode = sqlite3_step(ppStmt2);
   if (retCode == SQLITE_ROW) {
      soundFileSize     = sqlite3_column_int(ppStmt2, 0);
      mLog -> WriteToLog(wxT("GetAlphaElementsSoundFile Step size statement OK"));
   } // end if
   else {
      tempBuff.sprintf(wxT("GetAlphaElementsSoundFile Step size statement Failed...error code: %d"), retCode);
      mLog -> WriteToLog(tempBuff);
   } // end else

   retCode = sqlite3_finalize(ppStmt2);
   if (retCode == SQLITE_OK)
      mLog -> WriteToLog(wxT("GetAlphaElementsSoundFile Finalize size statement OK"));
   else {
      tempBuff.sprintf(wxT("GetAlphaElementsSoundFile Finalize size statement Failed...error code: %d"), retCode);
      mLog -> WriteToLog(tempBuff);
   } // end else

   ppStmt2 = NULL;
   pzTail2 = NULL;

   // Part 2, create databuffer to hold audio data
   char *dataBuffer = new char[soundFileSize];

   tempBuff.sprintf(wxT("SELECT SOUNDFILEDATA FROM ALPHAELEMENTS WHERE SOUNDFILENAME = '%s'"), soundFileName.GetData());

   retCode = sqlite3_prepare_v2(db, tempBuff.utf8_str(), -1, &ppStmt2, &pzTail2);
   if (retCode == SQLITE_OK) 
      mLog -> WriteToLog(wxT("GetAlphaElementsSoundFile Prepare data statement OK"));
   else {
      tempBuff.sprintf(wxT("GetAlphaElementsSoundFile Prepare data statement Failed...error code: %d"), retCode);
      mLog -> WriteToLog(tempBuff);
   } // end else
   
   retCode = sqlite3_step(ppStmt2);
   if (retCode == SQLITE_ROW) {
      dataBuffer = (char *) sqlite3_column_blob(ppStmt2, 0);
      mLog -> WriteToLog(wxT("GetAlphaElementsSoundFile Step data statement OK"));
   } // end if
   else {
      tempBuff.sprintf(wxT("GetAlphaElementsSoundFile Step data statement Failed...error code: %d"), retCode);
      mLog -> WriteToLog(tempBuff);
   } // end else

   // if soundfile exists, delete it, then create a new file and write the buffer to disk
   soundFileExists = wxFile::Exists(fileToCreate.GetData());
   if (soundFileExists == true)
      wxRemoveFile(fileToCreate.GetData());

   wxFile *audioFile = new wxFile(fileToCreate.GetData(), wxFile::write);

   if (audioFile -> IsOpened() == false) {
      mLog -> WriteToLog(wxT("GetAlphaElementsSoundFile Unable to open Audio File for writing."));
      return (1);
   } // end if

mLog -> WriteToLog(wxT("In Function CheckPoint 1"));

   bytesWrote = audioFile -> Write(dataBuffer, soundFileSize);
   audioFile -> Flush();
   audioFile -> Close();

tBuf.sprintf(wxT("size: %d   bytes written: %d"), soundFileSize, bytesWrote);
mLog -> WriteToLog(tBuf);

   // open and close a dummy file to release the hold on the real file.
   audioFile -> Open(dummyFile, wxFile::write);
   audioFile -> Close();

   delete (audioFile);

mLog -> WriteToLog(wxT("In Function CheckPoint 2"));

   retCode = sqlite3_finalize(ppStmt2);
   if (retCode == SQLITE_OK)
      mLog -> WriteToLog(wxT("GetAlphaElementsSoundFile Finalize data statement OK"));
   else {
      tempBuff.sprintf(wxT("GetAlphaElementsSoundFile Finalize data statement Failed...error code: %d"), retCode);
      mLog -> WriteToLog(tempBuff);
   } // end else

   ppStmt2 = NULL;
   pzTail2 = NULL;

mLog -> WriteToLog(wxT("About To Delete allocated buffer"));
   delete [] dataBuffer;
mLog -> WriteToLog(wxT("About To Exit Function"));

   return (retCode);

} // end GetAlphaElementsSoundFile
The debug log I created contains the following info after the crash...

Code: Select all

29-Jan-2012 15:31:10 - GetAlphaElementsSoundFile Prepare size statement OK
29-Jan-2012 15:31:10 - GetAlphaElementsSoundFile Step size statement OK
29-Jan-2012 15:31:10 - GetAlphaElementsSoundFile Finalize size statement OK
29-Jan-2012 15:31:10 - GetAlphaElementsSoundFile Prepare data statement OK
29-Jan-2012 15:31:10 - GetAlphaElementsSoundFile Step data statement OK
29-Jan-2012 15:31:10 - In Function CheckPoint 1
29-Jan-2012 15:31:10 - size: 24669   bytes written: 24669
29-Jan-2012 15:31:10 - In Function CheckPoint 2
29-Jan-2012 15:31:10 - GetAlphaElementsSoundFile Finalize data statement OK
29-Jan-2012 15:31:10 - About To Delete allocated buffer

User avatar
doublemax
Moderator
Moderator
Posts: 15170
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Deleting memory buffer crashes program and other strange

Post by doublemax » Sun Jan 29, 2012 10:46 pm

Code: Select all

char *dataBuffer = new char[soundFileSize];
// later:
dataBuffer = (char *) sqlite3_column_blob(ppStmt2, 0);
Something like this can never be correct. You're allocating a buffer, but the pointer is overwritten. So you can't actually use the buffer and you also can't free the buffer.

I'm not too familiar with low-level sqlite, i use wxSqlite3 which makes things a lot easier.
But after a quick glance at the sqlite docs, I'd say that you don't have to allocate a buffer for the Blob data. Sqlite does it and it's also freed automatically, so you must not free it yourself.

And to be safe, maybe you should get the size of the Blob from sqlite, too. Using sqlite3_column_bytes().
Use the source, Luke!

TexasJimbo
Knows some wx things
Knows some wx things
Posts: 28
Joined: Sun May 04, 2008 6:41 pm

Re: Deleting memory buffer crashes program and other strange

Post by TexasJimbo » Mon Jan 30, 2012 2:23 am

Thank you doublemax. I thought I had to provide the buffer but turns out as you mentioned, only the pointer....I have it working now. I also figured out that my access problem had to do with the file not being released when I call wxMediaCtrl::Load method...well it hangs onto the file until you load something else. I wanted to reuse the same file name to hold the clip I extract from my db...so that was my problem, trying to overwrite the same sound clip with a new one, while it is loaded by wxMediaCtrl::Load....I got around it by immediately before creating the new sound clip file, I load a dummy file with wxMediaCtrl::Load. Now it all works...thanks again!

Post Reply