Memory Pool

    This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

    • Memory Pool

      Hi!
      In the following method:

      Source Code

      1. unsigned char* MemoryPool::AllocateNewMemoryBlock(void)
      2. {
      3. // calculate the size of each block and the size of the actual memory allocation
      4. size_t blockSize = m_chunkSize + CHUNK_HEADER_SIZE; // chunk + linked list overhead
      5. size_t trueSize = blockSize * m_numChunks;
      6. // allocate the memory
      7. unsigned char* pNewMem = (unsigned char*)malloc(trueSize);
      8. if (!pNewMem)
      9. return NULL;
      10. // turn the memory into a linked list of chunks
      11. unsigned char* pEnd = pNewMem + trueSize;
      12. unsigned char* pCurr = pNewMem;
      13. while (pCurr < pEnd)
      14. {
      15. // calculate the next pointer position
      16. unsigned char* pNext = pCurr + blockSize;
      17. // set the next & prev pointers
      18. unsigned char** ppChunkHeader = (unsigned char**)pCurr;
      19. ppChunkHeader[0] = (pNext < pEnd ? pNext : NULL);
      20. // move to the next block
      21. pCurr += blockSize;
      22. }
      23. return pNewMem;
      24. }
      Display All


      Is it better to change this part of code :

      Source Code

      1. // set the next & prev pointers
      2. unsigned char** ppChunkHeader = (unsigned char**)pCurr;
      3. ppChunkHeader[0] = (pNext < pEnd ? pNext : NULL);


      to this :

      Source Code

      1. // set the next & prev pointers
      2. unsigned char* ppChunkHeader = pCurr;
      3. ppChunkHeader = (pNext < pEnd ? pNext : NULL);


      I don't know the reason of casting PCurr to Char** and using array index to assign. Is there any reason to do that?
      Thank you!
    • No, all that would do is cause the local ppChunkHeader variable to be overwritten.

      This function is allocating a chunk of memory. I used unsigned char here because it's a single byte, so it makes it easier for me to allocate the correct size. Casting to a pointer to a pointer lets me say "treat the thing I'm pointing to like a pointer rather than a character". If I didn't do this and just used *pCurr, it would only copy one byte out of node address.

      These types of patterns crop up when you're directly manipulating the structure of memory. Notice how GetNext() and SetNext() do something similar. Sometimes I want to treat it as a bunch of bytes, other times I need to treat it like a pointer to something else (specifically when I'm operating on the linked-list portion of the data structure).

      -Rez
    • Rez, thank you very much.
      Working with pointers is confusing and reading code that uses pointers is more confusing.
      Now I understand why you cast to pointer to pointer and I want to ask, is the following code correct?

      Source Code

      1. unsigned char** ppChunkHeader = reinterpret_cast<unsigned char**>(pCurr);
      2. ppChunkHeader[0] = (pNext < pEnd ? pNext : NULL);

      Based on the code pCurr points to the first byte of the chunk of memory. Is it correct that after casting pCurr to "pointer to pointer" and assigning it to the ppChunkHeader, that one byte will be extended to 4 byte (In my computer pointers are 4 byte), so one pointer will be created in the first 4 bytes of the chunk, because we need a pointer in the header of the chunk of memory. Is this a common way that compilers do when casting pointers to pointer to pointers? I think this way of casting is compiler dependent and it is not based on language rules.

    • Are these two equal?

      code:
      unsigned char** ppChunkHeader = (unsigned char**)pCurr;
      ppChunkHeader[0] = (pNext < pEnd ? pNext : NULL);


      code:
      unsigned char** ppChunkHeader = &pCurr;
      *ppChunkHeader = (pNext < pEnd ? pNext : NULL);


      In my opinion, they are not. Am i right?


      I wrote a simple code :

      Source Code

      1. #include <iostream>
      2. using namespace std;
      3. int main(int argc, char** argv)
      4. {
      5. char c = 'c';
      6. char * charPtr;
      7. charPtr = &c;
      8. char ** charPtrPtr = &charPtr;
      9. cout << &charPtr << endl;
      10. cout << charPtrPtr << endl;
      11. cout << *(*(charPtrPtr)) << endl;
      12. return 0;
      13. }
      14. //Output :
      15. // 002BF898
      16. // 002BF898
      17. // c
      Display All

      Based on the output they are equal.
    • I think your example does not reflect my question. I tested my question with this sample code ( i don't know why i did not do this first before asking a question :) ). They are not same here. And it is obvious that they are different. ( one of them is address of the variable "pchar", and other one is actual data in the "pchar" ). I can't believe how this confused me at first. Side effects of extensive usage of STL ( like vector, shared_ptr e.g. ) for me. :evil:

      Source Code

      1. int main()
      2. {
      3. char c = 'c';
      4. char *pChar = &c;
      5. char **ppChar = &pChar;
      6. char **ppChar2 = (char**) pChar;
      7. cout << ppChar << "," << ppChar2 << endl;
      8. // cout << **ppChar << **ppChar2 << endl; uncomment this line to get an exception
      9. return 0;
      10. }
      Display All


      I am sorry if i made the situation more confusing.

      The post was edited 1 time, last by column_vector ().

    • Hey @column_vector,

      You are correct, these two lines:

      Source Code

      1. unsigned char** ppChunkHeader = (unsigned char**)pCurr;
      2. unsigned char** ppChunkHeader = &pCurr;


      ...are not equal. The first copies the value stored in pCurr and copies it to ppChunkHeader - the (unsigned char **) is a typecast to force the compiler to allow you to do this.

      The second copies the address of pCurr and stores that in ppChunkHeader.

      Pointers can definitely be confusing - just take things one step at a time, experiment with cout and the debugger to watch what values are being assigned with different lines of code, and eventually you'll have an "a HA" moment.
      Mr.Mike
      Author, Programmer, Brewer, Patriot