Click here to Skip to main content
14,879,113 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have defined a pretty simple class that I'd like to manage an array of blocks of data, arrays of 256 bytes each, with a max number of 256 blocks. I'm using a std list to hold the arrays. For testing I'm creating a an array of same, memsetting it to 0, loading up the array with uint8_t data, inserting that block into the list, and then memsetting that block again with 0, loading it with new data, and inserting that. My results are like this:

uint8_t ablock[MAX];
string stuff = "Now is the time for all good men";
memcpy(&ablock[0], reinterpret_cast<const uint8_t*>(&stuff[0]), stuff.length());


I then invoke a class member to insert the data block into the list, a private member of the class. Appears to work fine. I then repeat the process re-using the data block after memsetting is again to 0. The data blocks are of type void, the intention is to make the class data types agnostic, as much as I can.

First insertion is fine. I can pull the block out and read it, converting from the void type to uint8_t and finally putting the data into a std string with the proper conversions, no problem.

The problem is when I insert a 2nd string of data into the class, even though I memset the buffer to 0 I'm getting what appears to be an offset situation.
2nd insert and pull of the data:

Now is tTo come to the aid of the party.
To come to the aid of the party.


Here's the relevant part of the code:

class MemMgr
{
    unsigned _idx;
    list<void*> _blocks;
    void* _mempool[MAX];

public:
    MemMgr(void);
    ~MemMgr(void) { }
    void* GetBlock(unsigned);

    void InsertBlock(void*);
    unsigned GetSize(void) { return _blocks.size(); }
    void clear(void) { _blocks.clear(); }

    void DisplayAll(void);
};

void
MemMgr::InsertBlock(void* block)
{
    if(sizeof(block) > MAX)
        throw runtime_error("Blocksize too big");

    if(_blocks.size() > MAX)
        throw runtime_error("Out of room");

    memcpy(&_mempool[_idx], block, MAX);
    _blocks.push_back(&_mempool[_idx++]);
}


The MemMgr constructor initializes the _idx member to 0;

I can post more code can be posted if necessary.

What I have tried:

Tracing through with my IDE (Qt Creator) but all the deugger shows are addresses, I can't see the contents of each block in the list.
Posted
Updated 22-Mar-21 16:31pm

It's hard to debug just looking at a sketch, but void* is the size of a pointer. So when you index _mempool, you're going to be incrementing by the size of a pointer (32 or 64 bits), not a byte. I would suggest trying uint8_t* instead of void*. My butt has been bitten by this kind of thing more than once.
   
There are several errors in this code. Here's one :
C++
MemMgr::InsertBlock(void* block)
{
    if(sizeof(block) > MAX)
        throw runtime_error("Blocksize too big");

    if(_blocks.size() > MAX)
        throw runtime_error("Out of room");

    memcpy(&_mempool[_idx], block, MAX);
    _blocks.push_back(&_mempool[_idx++]);
}
block is a pointer to a void type. In 64-bit code the size of block will always be size of eight bytes. I think you want to compare the amount of data in block to MAX and the only way you can do that is to pass it to the function.

The memcpy statement is incorrect and the only reason the app does not fail is because only MAX bytes are copied. The destination, the first argument, is the problem. Look again at the definition of mempool :
C++
void* _mempool[MAX];
It is declared an array of MAX void pointers. The memcpy statement copies into that array. What you really want is to copy block to one of the pointers in the array. In this case, the _idx'th one. That line should be written as :
C++
memcpy( _mempool[_idx], block, MAX );
if you want copy MAX bytes. This assumes that _mempool[ _idx ] has a valid address in it.

The line following it, the push_back statement, has the same problem. It is using the address of the pointer in the array instead of its value. It should look like this :
C++
_blocks.push_back( _mempool[_idx++] );
That is, if you want to add the actual pointer itself onto the list and not the address of the pointer. That is what I mean the value of the pointer.

One other thing - in my opinion the size of the data block and the number of data blocks should have two different names. They can certainly have the same values but I don't think the names should be the same because they refer to two entirely different things.
   
v2
Comments
Greg Utas 23-Mar-21 6:21am
   
Who needs a debugger when you're around? :) 5.
Rick York 23-Mar-21 11:43am
   
Thank you sir.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)




CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900