• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1831
  • Last Modified:

"Invalid allocation size" error. Help needed.

I am working on a C++ game application. It's being developed in Visual Studio C++ 2005, on a Windows XP SP2 machine, we use OGRE as our graphics engine, and Crazy Eddie GUI (CEGUI) for our user interfaces. When I attempt to run the game, it generates a breakpoint and this is the output:

...................................................................................
First-chance exception at 0x7c812a5b in starClient_d.exe: Microsoft C++ exception: CEGUI::UnknownObjectException at memory location 0x0012d5b4..
HEAP[starClient_d.exe]: Invalid allocation size - CCCCCD11 (exceeded 7ffdefff)
starClient_d.exe has triggered a breakpoint

The breakpoint occurs in the following line of code:

return Ogre::MemoryManager::instance().op_new_vc( reportedSize, gProcessID );

The call stack looks like this:

=>OgreMain_d.dll!0102d5b2()
OgreMain_d.dll!0102f5a6()
>starClient_d.exe!operator new[](unsigned int reportedSize=3435973837)  Line 363 + 0x23 bytes (Code A)
 starClient_d.exe!Star::InDataStream::readString()  Line 121 + 0x4f bytes (Code B)
starClient_d.exe!Star::Journal::deserializeJournalData(Star::InDataStream & ids={...})  Line 346 + 0x34 bytes (Code C)
starClient_d.exe!Star::Report::Report(Star::InDataStream & inDataStream={...})  Line 40 (Code D)

Where:

Code A
---------
inline void *operator new[](size_t reportedSize)
{
    if( !gProcessID )
        gProcessID = Ogre::MemoryManager::instance()._getProcessID();
 ERROR HERE==>   return Ogre::MemoryManager::instance().op_new_vc( reportedSize, gProcessID );
}

Code B
---------

std::string InDataStream::readString()
{
      int length;

      // read the length first
      length = readInt();

LINE 121==>      char* buffer = new char[length + 1];
      //char buffer[50];

      // Now read the string.
      mIS->read(buffer, length * sizeof(char));

      buffer[length] = 0;

      std::string tmp_string(buffer);

      delete[] buffer;

      return std::string(tmp_string);
}

Code C
---------
void Journal::deserializeJournalData(InDataStream& ids)
{
      //read the number of entries in this stream
      int numEntries = ids.readInt();

      //read the owner ID of this journal and set class data
      this->ownerID = ids.readInt();

      for(int i = 0; i < numEntries; i++)
      {
            //read the current entryItem-type
            int itemType = ids.readInt();
            Entry* entry;

            //Use the enumerated type to check if the entryItem is a
            //text or picture item
            switch(itemType)
            {
            case TEXT_ITEM:
                  //create a new entry and add it to the ToC
                  entry = newEntry(new TextItem(" "));

                  //Insert the stored values in the stream into the newly created entry
                  //in the order they were written
                  entry->setTimeStamp(ids.readInt());
                  entry->setEntryTitle(ids.readString());
LINE 346 ==>                  dynamic_cast<TextItem*>(entry->getEntryItemPtr())->setBody(ids.readString());

Code D
---------

Report::Report(InDataStream& inDataStream)
      {
            // Variables declaration and initialization.
            std::vector<Entry*> workTableOfContents = (*(this->getTableOfContents()));

            // Clear the vector of pointers to Entry objects.
            workTableOfContents.clear();

          this->deserializeJournalData(inDataStream);
LINE 40==>      }

Any help would be appreciated.











0
Lou1
Asked:
Lou1
2 Solutions
 
jkrCommented:
Seems that your input file is either invalid or processed incorrectly - since the length is read from the file using

      length = readInt();

and then directly used for the allocation in

      char* buffer = new char[length + 1];

the invalid allocation size of more than 2GB (0x7ffdefff - the *theoretical* limit) has its orifins here. I'd add some error handling code like

#define _2GB 0x7ffdefff

      length = readInt();

      if (length > _2GB) {

          // error handling here
      }

      char* buffer = new char[length + 1];

0
 
thuannguyCommented:
Hi,
Problem occurs in the length = readInt(); line of code B. The readInt function has returned an unexpected value (might be CCCCCD10, which exceeds the max-allowed value 7ffdefff).
BR,
Thuan.
0
 
jkrCommented:
Sorry, that's not 2GB, make that

#define ALLOC_LIMIT 0x7ffdefff

      length = readInt();

      if (length > ALLOC_LIMIT) {

          // error handling here
      }

      char* buffer = new char[length + 1];
0
Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

 
Lou1Author Commented:
FYI, the readInt function is as follows:

int InDataStream::readInt()
{
      int value;
      mIS->read((char*)&value, sizeof(int));

      return value;
}

Where mIS is declared as follows:

protected:
      // istream associated with this DataStream.
      std::istream *mIS;

0
 
jkrCommented:
That was cleat. Yet the input seems to be in a different format or corrupted. Check it or output the value after reading it vor debugging/verification purposes. BTW, is the file opened as 'binary'?
0
 
itsmeandnobodyelseCommented:
You should add some more error checking, i. e. the readInt has no error check nor an initialization and would return some random values on failing:

int InDataStream::readInt()
{
      int value = 0;    // always init variables (it costs less than nano-seconds)
      if (mIS->read((char*)&value, sizeof(int)))
           return value;
     // throw exception or return 0 or -1 which was needed to be
     // checked by  the calling function as well
}

>>>> dynamic_cast<TextItem*>(entry->getEntryItemPtr())->setBody(ids.readString());
You should avoid statements like that. It is really bad code:

1. there are really rare cases where dynamic casts were needed. Here it is not. A few lines above you create the TextItem by new. If you would save the pointer in a variable you wouldn't need the cast.

    TextItem* textentry = new TextItem(" ");
    entry = newEntry(textentry );
    ...
    std::string s = ids.readString();
    textentry->setBody(s);

I wonder whether the TextItem was derived from a common baseclass. If not the dynamic_cast makes even less sense. If so, you should consider to make the setBody a virtual function of the baseclass wha tis much much better than using dynamic_cast.

Regards, Alex




0
 
Lou1Author Commented:
Well, I found out the error was occurring in another developer's code. I told them about their error and now it's up to them to fix it.

But thanks to all who responded.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Get expert help—faster!

Need expert help—fast? Use the Help Bell for personalized assistance getting answers to your important questions.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now