?
Solved

"Invalid allocation size" error. Help needed.

Posted on 2007-07-22
7
Medium Priority
?
1,777 Views
Last Modified: 2008-01-09
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
Comment
Question by:Lou1
7 Comments
 
LVL 86

Accepted Solution

by:
jkr earned 750 total points
ID: 19543267
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
 
LVL 6

Assisted Solution

by:thuannguy
thuannguy earned 750 total points
ID: 19543278
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
 
LVL 86

Expert Comment

by:jkr
ID: 19543294
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
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:Lou1
ID: 19543469
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
 
LVL 86

Expert Comment

by:jkr
ID: 19543520
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
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 19546156
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
 

Author Comment

by:Lou1
ID: 19601694
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

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

When writing generic code, using template meta-programming techniques, it is sometimes useful to know if a type is convertible to another type. A good example of when this might be is if you are writing diagnostic instrumentation for code to generat…
Often, when implementing a feature, you won't know how certain events should be handled at the point where they occur and you'd rather defer to the user of your function or class. For example, a XML parser will extract a tag from the source code, wh…
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.
Suggested Courses

809 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question