C++ bad_alloc caused by new? - c++

[Fore note: I have read the existing threads in StackOverflow. None seemed to be on my question]
I am looking into the Quake 2 MD2 format. I seem to be getting a bad allocation after new'ing a pointer-array. However, if I do some horrible pointer manipulation, everything is fine.
I guess the question is, why am I getting such an exception?
The first "MD2Model::Load" works. The one I posted after it gets the exception.
Basic structures :
struct MD2Header
{
int nIdentifier;
int nVersion;
int nSkinWidth;
int nSkinHeight;
int nFrameSize;
int nNumSkins;
int nNumVertices;
int nNumUV;
int nNumTriangles;
int nNumCmds;
int nNumFrames;
int nOffsetSkins;
int nOffsetUV;
int nOffSetTriangles;
int nOffsetFrames;
int nOffsetCmds;
int nOffsetEnd;
};
struct MD2Skin
{
char szName[64];
};
struct MD2TexCoord
{
short t;
short u;
};
struct MD2Triangle
{
short nVertex[3];
short tu[3];
};
struct MD2Vertex
{
float fVertex[3];
float fNormal[3];
};
struct MD2Frame
{
char szName[16];
MD2Vertex* pVerts;
};
And now, the function that reads the .md2 file:
bool MD2Model::Load( const char* pszName )
{
FILE* pFile = NULL;
fopen_s( &pFile, pszName, "rb" );
if( !pFile )
return false;
/* Read Header */
fread( &m_Header, sizeof(MD2Header), 1, pFile );
/* Allocate Pointers */
m_pSkins = new MD2Skin[m_Header.nNumSkins];
m_pTexCoords = new MD2TexCoord[m_Header.nNumUV];
m_pTriangles = new MD2Triangle[m_Header.nNumTriangles];
m_pFrames = new MD2Frame[m_Header.nNumFrames];
/* Read Skins */
fseek( pFile, m_Header.nOffsetSkins, SEEK_SET );
fread( m_pSkins, sizeof(MD2Skin), m_Header.nNumSkins, pFile );
/* Read Texture Coords */
fseek( pFile, m_Header.nOffsetUV, SEEK_SET );
fread( m_pTexCoords, sizeof(MD2TexCoord), m_Header.nNumUV, pFile );
/* Read Faces */
fseek( pFile, m_Header.nOffSetTriangles, SEEK_SET );
fread( m_pTriangles, sizeof(MD2Triangle), m_Header.nNumTriangles, pFile );
/* Read Animations */
struct stMD2Vertex
{
unsigned char nVertex[3];
unsigned char nLightNormalIndex;
};
struct stMD2Frame
{
float fScale[3];
float fTranslate[3];
char szName[16];
stMD2Vertex verts[1];
};
unsigned char pBuffer[30000];
stMD2Frame* pTmp = (stMD2Frame*) pBuffer;
fseek( pFile, m_Header.nOffsetFrames, SEEK_SET );
for( int i = 0; i < m_Header.nNumFrames; i++ )
{
fread( pTmp, 1, m_Header.nFrameSize, pFile );
m_pFrames[i].pVerts = new MD2Vertex[m_Header.nNumVertices];
strcpy_s( m_pFrames[i].szName, pTmp->szName );
for( int j = 0; j < m_Header.nNumVertices; j++ )
{
m_pFrames[i].pVerts[j].fVertex[0] = pTmp->verts[j].nVertex[0] *
pTmp->fScale[0] + pTmp->fTranslate[0];
m_pFrames[i].pVerts[j].fVertex[2] = -1 * (pTmp->verts[j].nVertex[1] *
pTmp->fScale[1] + pTmp->fTranslate[1]);
m_pFrames[i].pVerts[j].fVertex[1] = pTmp->verts[j].nVertex[2] *
pTmp->fScale[2] + pTmp->fTranslate[2];
}
}
return true;
}
Variables dumped during debugging:
nNumSkins 1 int
nNumVertices 583 int
nNumUV 582 int
nNumTriangles 422 int
nNumFrames 1 int
(I ended up removing my D3DXVECTOR3 structures to see, so it's kinda fugly..)
Alright. So, inside the 'for' loop, is where it blows up.
If I were to do it like this:
// unsigned char pBuffer[30000];
// stMD2Frame* pTmp = (stMD2Frame*) pBuffer;
fseek( pFile, m_Header.nOffsetFrames, SEEK_SET );
for( int i = 0; i < m_Header.nNumFrames; i++ )
{
stMD2Frame* pTmp = new stMD2Frame();
fread( pTmp, 1, m_Header.nFrameSize, pFile );
m_pFrames[i].pVerts = new MD2Vertex[m_Header.nNumVertices];
strcpy_s( m_pFrames[0].szName, pTmp->szName );
I get the bad_alloc exception during allocating the "m_pFrames[i].pVerts" statement.
Sometimes, I don't get it, but I do get the exception when I try to new my D3D class (I'm assuming I'll get it no matter what I new afterwards).
My MEM usage is extremely low, so could it be heap corruption?
I actually had to end up doing this during creating my VertexBuffer during animations as well.
Should I end up using vectors? I know they allocate more than needed, but it seems like the (most obvious)[best] way.

I would check the line:
strcpy_s( m_pFrames[0].szName, pTmp->szName );
If the string loaded from the file is not null-terminated then this copy could end up overwriting your stack space and causing corruption.
EDIT
Looking again, I think the problem is that you define stMD2Frame as
struct stMD2Frame
{
float fScale[3];
float fTranslate[3];
char szName[16];
stMD2Vertex verts[1];
};
but this only has space for one vertex.
When you read in the frame as
fread( pTmp, 1, m_Header.nFrameSize, pFile );
you will corrupt your memory.
I suggest a check that
sizeof(stMD2Frame)>=m_Header.nFrameSize
before reading the data.

Related

Why do changes to buffer in thread not be reflected in buffer on mainThread?

I'm trying to receive audio from the soundcard via RtAudio Api. It has a callback function that gets called once the audio has enough bytes received and the user can then copy the data to a custom object. This custom object can be sent to the callback via pointer. My class that encapsulates RtAudio looks like this:
class Audio {
private:
AudioConfiguration config;
AudioData data;
RtAudio* rt;
// the void* d is the casted AudioData-object
static int input( void*, void* inputBuffer, unsigned int bufferSize, double, RtAudioStreamStatus status, void* d );
void openStream( RtAudio::StreamParameters& params, RtAudio::StreamOptions& options, AudioConfiguration& config );
bool isDeviceOk();
public:
// ctor & dtor
Audio( AudioConfiguration& c );
~Audio();
// copy ctor & assignment
Audio( const Audio& other );
Audio& operator=( const Audio& a );
// move ctor & assignment
Audio( Audio&& other );
Audio& operator=( Audio&& a);
AudioConfiguration& getConfiguration();
AudioData& getData();
void start();
void stop();
};
This is the implementation of the static function that gets called from inside the audio thread
int Audio::input( void*, void* inputBuffer, unsigned int bufferSize, double, RtAudioStreamStatus status, void* d ){
if( status == RTAUDIO_INPUT_OVERFLOW )
std::cout << "Audio Thread: Input overflow detected." << std::endl;
//std::cout << "Audio Thread: Received input from soundcard" << std::endl;
float* in = static_cast<float*>( inputBuffer );
AudioData* data = static_cast<AudioData*>( d );
boost::lock_guard<boost::mutex> lock{data->getMutex()};
unsigned int i = 0;
while( i < bufferSize ){
data->getBuffer().push_back( *in );
in++;
i++;
}
return 0;
}
The custom object that I share between the threads is of the class AudioData, which looks like this:
class AudioData {
private:
boost::circular_buffer<float> buffer;
boost::mutex mutex;
public:
AudioData();
~AudioData();
boost::circular_buffer<float>& getBuffer();
boost::mutex& getMutex();
};
The audio-object gets embedded in a Recorder-Object, which then reads the buffer in the AudioData member variable of Audio.
typedef boost::container::vector<boost::circular_buffer<float>> Buffers;
class Recorder {
private:
Audio audio;
Buffers buffers;
/*
* Reads n samples per channel from audio buffers to NUM_CHANNELS distinct buffers
* When done, it returns the number of samples read into each channel
* Why? We want to keep audio buffer to be locked as minimal time as possible
*/
unsigned int read( unsigned int samples );
/*
* Deletes n samples from channel buffer
* When done, it returns the number of samples deleted
*/
unsigned int deleteBegin( unsigned int ch, unsigned int samples );
/*
* Detects the trigger on TRIGGER_CHANNEL
* Returns true, if trigger was found and its position
*/
bool detectTrigger( unsigned int* pos );
public:
Recorder( AudioConfiguration& c );
Recorder( Audio&& a );
boost::container::vector<float> record( RecorderConfiguration& config );
};
The function record(..) looks like this:
boost::container::vector<float> Recorder::record( RecorderConfiguration& config ){
AudioConfiguration audioConfig = audio.getConfiguration();
unsigned int length = ( audioConfig.fs * config.length ) / 1000;
boost::container::vector<float> recording;
recording.resize( length );
// Tell Audio to start recording
audio.start();
// State
unsigned int times = 0; // Count averages
unsigned int left = length; // Samples left on current average
bool triggered = false; // Trigger has been read
while( true ){
// Read into local buffer
unsigned int samplesToRead = length / 10;
unsigned int samplesRead = read( samplesToRead );
// if not enough samples, wait for more
if( samplesRead < 100 )
continue;
// Actual logic
unsigned int triggerPos = 0;
if( !triggered && detectTrigger( &triggerPos ) ){
std::cout << "Recorder: Trigger detected." << std::endl;
triggered = true;
// delete everything that comes before trigger on both channels
for( unsigned int i = 0 ; i < NUM_CHANNELS ; i++ ){
deleteBegin( i, triggerPos - 1);
}
}
// Copy from buffer if trigger was found beforehand
if( triggered ){
boost::circular_buffer<float>& buffer = buffers[ EEG_CHANNEL ];
unsigned int samplesToCopy = buffer.size();
if( samplesToCopy > left )
samplesToCopy = left;
for( unsigned int i = 0 ; i < samplesToCopy ; i++ ){
recording[ length - left ] = recording[ left - left ] + buffer.front();
buffer.pop_front();
left--;
}
}
// current average done
if( left <= 0 ){
// increment times
times++;
// check if recording is done
if( times >= config.times )
break;
// if not
else {
triggered = false;
left = length;
}
}
}
// Stop receiving input from audio
audio.stop();
return recording;
}
I read that the heap is the place to hold data that is shared between threads, but in the example by rtaudio they use a global variable that gets allocated on the stack for pushing the data to Link. So I am a little bit confused. Help would be gladly accepted!
Edit: When i debug my app. I can see that the input function of the audio-thread gets called and it writes to the buffer. Also the record function works as expected. Only the buffer (of AudioData) does not seem to have any data in it...
Edit2: Here is the code where I register the callback in the rtaudio api.
void Audio::openStream( RtAudio::StreamParameters& params, RtAudio::StreamOptions& options, AudioConfiguration& config ){
try {
rt->openStream( nullptr, &params, RTAUDIO_FLOAT32, config.fs, &config.bufferSize, &this->input, &data, &options, nullptr );
} catch( RtAudioError& e ){
std::cout << "Audio::openStream(): Cannot open stream." << std::endl;
throw e;
}
}

c++ sqllite3 reading blob won't work

Can someone guide me please,
I can't seem to read my blob correctly.
I don't know what's wrong, can somebody help?
this is my function:
what i'm trying to do is:
read the bob as binary and store the bytes in a char *data;
can someone please help?
int baramdb::dbreadblob(int pid)
{
sqlite3_stmt *res;
const char *tail;
int count = 0;
this->dbopen(this->dbfile);
if (sqlite3_prepare_v2(this->db, "SELECT * FROM Packet_Send_Queue", 128, &res, &tail) != SQLITE_OK)
{
printf("[Baram] Can't retrieve data: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
return(1);
}
while (sqlite3_step(res) == SQLITE_ROW)
{
int *plength = 0;
*plength = sqlite3_column_bytes(res, 2);
unsigned char **pbuffer = (unsigned char **)malloc(*plength);
memcpy(*pbuffer, sqlite3_column_blob(res, 0), *plength);
count++;
}
sqlite3_close(this->db);
this->lastresult = count;
return count;
}
It seems you don't understand what "pointer" really is and how to use it.
Then, sqlite3_column_bytes returns int not int*:
int length = sqlite3_column_bytes(res, 2);
This is absolutely incorrect in current case:
unsigned char **pbuffer = (unsigned char **)malloc(*plength);
If you're using C++ - try to not explicitly use malloc/new, use smart pointer or STL containers instead:
std::vector<char> data( length );
const char *pBuffer = reinterpret_cast<const char*>( sqlite3_column_blob(res, 2) );
std::copy( pBuffer, pBuffer + data.size(), &data[0] );
This is it.

Efficient way of reading part of a file into an std::vector<char>?

Refering to this question: Efficient way of reading a file into an std::vector<char>?
I need a function that does the followig thing:
void readFromFile( std::vector< unsigned char >& buffer,
string filename,
size_t offset, size_t count );
so the function read from the file from offset to offset + count into vector;
void readFromFile( std::vector< unsigned char >& buffer,
string filename,
size_t offset, size_t count )
{
// get file size and reallocate the buffer
size_t fsize = filesize( filename );
buffer.reserve( buffer.size() + size );
// open the file
ifstream file( filename );
// first way
file.seekg( offset );
file.read( ???? )
// second way
istreambuf_iterator< unsigned char > from( file );
istreambuf_iterator< unsigned char > eof;
advance( from, offset );
copy( from, eof, back_inserter( buffer );
}
In the first way I don't know how to read the file at once. In the second way the read operation is quite slow because I read byte per byte.
Are better alternatives?
EDIT
Thanks to #Ben Voigt
I wrote this two simple functions:
inline std::streamsize filesize( const std::string& filename )
{
std::ifstream in( filename, std::ifstream::in | std::ifstream::binary );
if ( !in ) throw std::invalid_argument
{
"filesize error: invalid filename"
};
in.seekg( 0, std::ifstream::end );
return in.tellg();
// here the file is closed. so no need to restore the get pointer
}
inline std::streamsize filesize( std::ifstream& file )
{
file.seekg( 0, std::ifstream::end );
const auto size = file.tellg();
file.seekg( 0 ); // restore the get pointer
return size;
}
template< typename RAIter >
inline void read_file( std::istream& file,
RAIter first, RAIter last,
std::streamsize offset = 0
)
{
const auto size = last - first;
file.seekg( offset, std::ifstream::beg );
file.read( reinterpret_cast< char* >( &*first ), size );
}
template<>
inline void read_file( std::istream& file,
unsigned char* first, unsigned char* last,
std::streamsize offset /*= 0 no default argument in template spacalization. */
)
{
const auto size = last - first;
file.seekg( offset, std::ifstream::beg );
file.read( reinterpret_cast< char* >( first ), size );
}
so the function now became easy:
vector< unsigned char > buffer;
// do something with buffer
const string filename{ "blabla" };
const auto size = filesize( filename );
// resize the buffer
auto const OLD_LEN = buffer.size();
buffer.resize( OLD_LEN + size );
size_t startOffset = 0; // from where to star reading from file
size_t cont = size; // how manny bytes read from file
// read filename from startOffset to startOffset + count, appendeing in buffer
ifstream file( filename );
read_file( file,
buffer.data() + OLD_LEN,
buffer.data() + OLD_LEN + count,
startOffset
);
auto old_end = buffer.size();
buffer.resize( old_end + blocksize );
//...
file.read( &buffer[old_end], blocksize );
auto actual_size = file.gcount;
if (actual_size < blocksize) buffer.resize(old_end + actual_size);
Here's a quick and efficient way of getting a character array from a file.
char * arr;
int len;
// Function that opens a file, needing the file name
void openFile(const char* fileName)
{
ifstream file(fileName, ios::in);
if(!file.is_open()) return;
file.seekg(0, file.end);
// Get the length of the file
len = file.tellg();
file.seekg(0, file.beg);
arr = new char[len];
file.read(arr, len);
file.close();
}
After that you can just push the char array into a vector.

FIFO Communication between two different process c++

Hi please some one help me
I've two process say some X and Y.
X and Y both have the following information
typedef enum {
HEALTHY=1,
FAULTY=2,
CHANGE=3,
ERROR=4
} MsgTypeT;
typedef struct {
char role[16];
char state[16];
char info[256];
} InfoT;
typedef struct {
MsgTypeT type;
int size;
InfoT *data;
} MsgT;
Here the condition is that if process Y sends an information process X will read it
So i used fifo between x and y
Y has a function write buffer which writes to fifo and code is as following
int write_buffer(HA_DEVMON_MsgT const* send)
{
char* dest = buffer;
memcpy( dest, &send->type, sizeof( MsgTypeT ));
dest += sizeof(MsgTypeT);
memcpy( dest, &send->size, sizeof( int ));
dest += sizeof(int);
memcpy( dest, send->data, sizeof( InfoT ));
dest += sizeof(InfoT);
int byteCount = write( this->fifo_fd, buffer, dest - buffer );
if ( byteCount != dest - buffer ) {
cout<<"Error in writing ";
}
return byteCount == dest - buffer ? 0 : -1;
}
I think it's writing perfectly because cout statements are working fine also when tried to output nbytes it gave 512bytes have been written
Now when X tries to read it's giving null values for role and state also size its giving 6441568
Its only giving MsgTypeT correct other values are null :(
The code is as follows--- I'm doing something wrong please correct it
int readMsg(MsgT *msg)
{
int rCode=0, nbytes=0;
char buffer[512]={0};
nbytes = read(this->get_handle(), buffer, sizeof(buffer));
if (nbytes < 0) {
cout<<"error in read";
rCode=-1;
}
if (rCode == 0) {
char *p_src = (char *)buffer;
mempcpy(&msg->type, p_src, sizeof(MsgTypeT));
p_src+=sizeof(MsgTypeT);
mempcpy(&msg->size, p_src, sizeof(int));
p_src+=sizeof(int);
msg->data = new InfoT(); //allocating memory (needed or not???)
mempcpy(msg->data, p_src, sizeof(InfoT));
p_src+=sizeof(InfoT);
}
return rCode;
}
In readMsg, your last mempcpy writes to msg, not to the
InfotT you just allocated.
Also, but I suppose you know this: this is only guaranteed to
work if both processes were compiled with the same compiler,
using the same options. (In practice, it's likely to work if
the underlying system defines its API in terms of C, which is
the case for Windows and Unix.)
EDIT:
Further: you have the same problem when writing. You write
sizeof(InfoT) (288) bytes, but you write the pointer (and then
a lot of garbage), not the data it's pointing to.
And you increment the pointer into the MsgT object. This is
likely not to work, if there is any padding. What you really
have to do is:
int
write_buffer( MsgT const* data )
{
char buffer[512] = {}; // Or better yet, std::vector<char>
char* dest = buffer;
memcpy( dest, &data->type, sizeof( MsgTypeT ) );
dest += sizeof( MsgTypeT );
memcpy( dest, &data->size, sizeof( int ) );
dest += sizeof( int );
memcpy( dest, &data->data, sizeof( InfoT ) );
dest += sizeof( InfoT );
int byteCount = write( fifo_fd, buffer, dest - buffer );
if ( byteCount != dest - buffer ) {
std::cerr << "Error in write" << std::endl;
}
return byteCount == dest - buffer ? 0 : -1;
}
and the opposite when reading.
And once again, this will only really work for two processes on
the same machine, compiled with the same compiler using the same
options. A better solution would probably be to define
a protocol, with a defined representation of integers, strings,
etc., format your output to that representation, and parse it
for your input. That way, it will still work even if one of the
processes is 64 bits, and the other 32.

Bus Error on fopen()?

I am using Totalview to debug some code, and it is stopping with a Bus Error.
What is this, and how do I fix it? here is the code snip
In my main:
char *infilename = "/home/dcole/Images/lena1024s.jpg";
/* Try opening a jpeg*/
if( read_jpeg_file( infilename ) > 0 )
{
//do some stuff
}
The function:
int read_jpeg_file( const char *filename )
{
/* these are standard libjpeg structures for reading(decompression) */
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
/* libjpeg data structure for storing one row, that is, scanline of an image */
JSAMPROW row_pointer[1];
FILE *infile = fopen( filename, "rb" ); //this line is where the debugger stops with a Bus Error
unsigned long location = 0;
int i = 0;
if ( !infile )
{
printf("Error opening jpeg file %s\n!", filename );
return -1;
}
return 1;
}
The file I am passing in does exist. I can see that it shows up as the right sting to the full path in the debugger.
I think you're having a memory access problem because of the filename variable...
Instead of:
char *infilename = "/home/dcole/Images/lena1024s.jpg";
try using:
char infilename[] = "/home/dcole/Images/lena1024s.jpg";