In FreeRTOS, there is only malloc and free , but there is no calloc and realloc . I need realloc and I tried to implement it myself. Is everything right here? The memory management module itself can be found here .

 void *pvPortRealloc(void *ptr, size_t s) { uint8_t *puc = ( uint8_t * ) ptr; BlockLink_t *pxLink; void *newBlock; if (ptr != NULL) { puc -= heapSTRUCT_SIZE; pxLink = (void*) puc; vTaskSuspendAll(); { newBlock = pvPortMalloc(s); memcpy(newBlock, ptr, pxLink->xBlockSize); vPortFree(ptr); } xTaskResumeAll(); return newBlock; } return NULL; } 

Here is the new version created after the AnT comments.

 void *pvPortRealloc(void *ptr, size_t s) { uint8_t *puc = ( uint8_t * ) ptr; BlockLink_t *pxLink; void *newBlock; extern void memcpy( void*, void*, size_t ); size_t blockSize; if (ptr == NULL) { newBlock = pvPortMalloc(s); } else { puc -= heapSTRUCT_SIZE; pxLink = (void*) puc; blockSize = pxLink->xBlockSize - heapSTRUCT_SIZE; if (s == 0) { newBlock = NULL; } else if (s > blockSize) { vTaskSuspendAll(); { newBlock = pvPortMalloc(s); if (newBlock != NULL) { memcpy(newBlock, ptr, blockSize); vPortFree(ptr); } } xTaskResumeAll(); } else //s < blockSize { vTaskSuspendAll(); { size_t newBlockSize = s + heapSTRUCT_SIZE + ( portBYTE_ALIGNMENT - ( s & portBYTE_ALIGNMENT_MASK ) ); //if right segment is to few, do nothing if (pxLink->xBlockSize - newBlockSize > heapSTRUCT_SIZE) { //split current block pxLink->xBlockSize = newBlockSize; BlockLink_t *blockToFree = (void*)((uint8_t*)pxLink + pxLink->xBlockSize); blockToFree->xBlockSize = blockSize + heapSTRUCT_SIZE - pxLink->xBlockSize; //free second part prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) blockToFree ) ); xFreeBytesRemaining += blockToFree->xBlockSize; } newBlock = ptr; } xTaskResumeAll(); } } return newBlock; } 
  • And where is the release of memory at s = 0 ? What will happen if the size is equal to the previous one? - 0andriy
  • do not do suspend-resume. Inside malloc / free, it is already there, no longer needed. - Alexey Esaulenko
  • @AlexeyEsaulenko, why? After all, in pvPortMalloc and vPortFree this is done. - maestro
  • Perhaps it was necessary to write more. In malloc / free, you work with a shared memory pool, which can be accessed simultaneously from different threads. And here all the variables belong to the same thread. - Alexey Esaulenko
  • Yes, and read freertos.org/a00111.html about different types of heap. The implementation that you have taken, with the active allocation-release, will enfold the entire memory. - Alexey Esaulenko

1 answer 1

  1. It is striking that your realloc immediately returns a null pointer if a null pointer arrives at the input. This is already wrong. Standard realloc(NULL, size) should work like malloc(size) .

  2. And where is the test that s can be smaller than the original size? What makes you think that you can just do it

     memcpy(newBlock, ptr, pxLink->xBlockSize); 

    ?

  3. (Variation 2) When querying for a zero size, standard realloc has implementation-defined behavior with a specified set of options. You have, if 0 gets to pvPortMalloc , then pvPortMalloc will return a null pointer. You are not ready for this.

  4. And where is the processing of failed allocation?


After correction:

When calling realloc with a size of 0 standard realloc does not guarantee the release of old memory (this is not explicitly stated in the standard, but cppreference.com states that the standard should be interpreted that way). Your implementation formally fits into this behavior. But perhaps it would be more elegant with the return of a null pointer to free the old block of memory. Maybe...

  • It’s better to use memmove around memcpy . When using memmove the memory area may overlap. - Yaroslav
  • @Yaroslav, there is not. Blocks allocated with malloc do not overlap. - maestro