malloc(): invalid size (unsorted) on new unsigned char[<size>]

Viewed 7020

There are enormous amounts of memory-error related posts here on SO but none addresses my problem.

Consider this class (definition and declaration merged for an easy read):

#define SIZEMACRO(mem) *reinterpret_cast<uint32_t *>(mem)
class StoredRecord {
  uint64_t idx;
  unsigned char* mem;
 public:
  ~StoredRecord() { 
    delete[] mem;
  }

  StoredRecord() : idx(0), mem(nullptr) {}

  StoredRecord(uint64_t _idx, unsigned char* _mem) : idx(_idx), mem(new unsigned char[SIZEMACRO(_mem)]) {
    memcpy(mem, _mem, SIZEMACRO(_mem));
  }

  static std::shared_ptr<StoredRecord> createShared(uint64_t _idx, unsigned char* _mem) {
    return std::make_shared<StoredRecord>(_idx, _mem);
  }

  // Some getter for idx and mem
};

It doesnt do much, takes the memory and uses SIZEMACRO() (which evaluates the first bytes as uint32_t and uses this as the size, works well) to determinate the size of the memory chunk, allocates the same size and copies it.

These StoredRecord are kept in an std::vector<std::shared_ptr<StoredRecord>> m_records in another class. No problem here whats-o-ever. However, the code crashes when used as follows:

const uint32_t a = 1800;
const uint32_t b = 1900;
const uint32_t c = 2000;
unsigned char data1[a]; 
unsigned char data2[b];
unsigned char data3[c];
memset(data1, 0, a);
memset(data2, 0, b);
memset(data3, 0, c);
memcpy(data1, &a, sizeof(uint32_t));
memcpy(data2, &b, sizeof(uint32_t));
memcpy(data3, &c, sizeof(uint32_t));
m_records.push_back(StoredRecord::createShared(0, data1)); // fine
m_records.push_back(StoredRecord::createShared(1, data2)); // fine

// crashes with "malloc(): invalid size (unsorted)"
// at mem(new unsigned char[SIZEMACRO(_mem)])
m_records.push_back(StoredRecord::createShared(2, data3)); 

However, if I decrease c = 1900 everything is fine. With a, b or c above ~1950, it crashes with the malloc invalid size when run with GDB or run normaly. I've also run my code with valgrind, there no crash happens and it dosn't even complain about that new unsigned char. I already double-checked the SIZEMACRO() and it evaluates fine to 1800, 1900 and 2000. What puzzles me is the error-message "invalid size". Why can't I malloc more then ~1950 bytes here?

0 Answers
Related