Что может быть хорошим способом обнаружения утечки памяти C ++ во встроенной среде? Я пытался перегрузить новый оператор для регистрации каждого распределения данных, но я, должно быть, сделал что-то не так, этот подход не работает. Кто-нибудь еще сталкивался с подобной ситуацией?
Это код перегрузки оператора new и delete.
EDIT:
Полное раскрытие: я ищу утечку памяти в моей программе и использую этот код, который кто-то другой написал для перегрузки оператора new и delete. Часть моей проблемы заключается в том, что я не до конца понимаю, что она делает. Я знаю, что цель состоит в том, чтобы зарегистрировать адрес вызывающего и предыдущего абонента, размер выделения, 1, если мы выделяем, 2, если мы освобождаем. плюс имя потока, который работает.
Спасибо за все предложения, я собираюсь попробовать другой подход, который кто-то здесь на работе предложил. Если это сработает, я опубликую это здесь.
Еще раз спасибо всем вам, первоклассным программистам, за то, что нашли время ответить.
StackOverflow пород!
Заключение
Спасибо за все ответы. К сожалению, мне пришлось перейти к другой более насущной проблеме. Эта утечка произошла только по крайне маловероятному сценарию. Я чувствую дерьмо из-за того, что просто уронил его, я могу вернуться к нему, если у меня будет больше времени. Я выбрал ответ, который, скорее всего, буду использовать.
#include <stdlib.h>
#include "stdio.h"
#include "nucleus.h"
#include "plus/inc/dm_defs.h"
#include "plus/inc/pm_defs.h"
#include "posix\inc\posix.h"
extern void* TCD_Current_Thread;
extern "C" void rd_write_text(char * text);
extern PM_PCB * PMD_Created_Pools_List;
typedef struct {
void* addr;
uint16_t size;
uint16_t flags;
} MemLogEntryNarrow_t;
typedef struct {
void* addr;
uint16_t size;
uint16_t flags;
void* caller;
void* prev_caller;
void* taskid;
uint32_t timestamp;
} MemLogEntryWide_t;
//size lookup table
unsigned char MEM_bitLookupTable[] = {
0,1,1,2,1,2,2,3,1,2,2,3,1,3,3,4
};
//#pragma CODE_SECTION ("section_ramset1_0")
void *::operator new(unsigned int size)
{
asm(" STR R14, [R13, #0xC]"); //save stack address temp[0]
asm(" STR R13, [R13, #0x10]"); //save pc return address temp[1]
if ( loggingEnabled )
{
uint32_t savedInterruptState;
uint32_t currentIndex;
// protect the thread unsafe section.
savedInterruptState = NU_Local_Control_Interrupts(NU_DISABLE_INTERRUPTS);
// Note that this code is FRAGILE. It peeks backwards on the stack to find the return
// address of the caller. The location of the return address on the stack can be easily changed
// as a result of other changes in this function (i.e. adding local variables, etc).
// The offsets may need to be adjusted if this function is touched.
volatile unsigned int temp[2];
unsigned int *addr = (unsigned int *)temp[0] - 1;
unsigned int count = 1 + (0x20/4); //current stack space ***
//Scan for previous store
while ((*addr & 0xFFFF0000) != 0xE92D0000)
{
if ((*addr & 0xFFFFF000) == 0xE24DD000)
{
//add offset in words
count += ((*addr & 0xFFF) >> 2);
}
addr--;
}
count += MEM_bitLookupTable[*addr & 0xF];
count += MEM_bitLookupTable[(*addr >>4) & 0xF];
count += MEM_bitLookupTable[(*addr >> 8) & 0xF];
count += MEM_bitLookupTable[(*addr >> 12) & 0xF];
addr = (unsigned int *)temp[1] + count;
// FRAGILE CODE ENDS HERE
currentIndex = currentMemLogWriteIndex;
currentMemLogWriteIndex++;
if ( memLogNarrow )
{
if (currentMemLogWriteIndex >= MEMLOG_SIZE/2 )
{
loggingEnabled = false;
rd_write_text( "Allocation Logging is complete and DISABLED!\r\n\r\n");
}
// advance the read index if necessary.
if ( currentMemLogReadIndex == currentMemLogWriteIndex )
{
currentMemLogReadIndex++;
if ( currentMemLogReadIndex == MEMLOG_SIZE/2 )
{
currentMemLogReadIndex = 0;
}
}
NU_Local_Control_Interrupts(savedInterruptState);
//Standard operator
//(For Partition Analysis we have to consider that if we alloc size of 0 always as size of 1 then are partitions must be optimized for this)
if (size == 0) size = 1;
((MemLogEntryNarrow_t*)memLog)[currentIndex].size = size;
((MemLogEntryNarrow_t*)memLog)[currentIndex].flags = 1; //allocated
//Standard operator
void * ptr;
ptr = malloc(size);
((MemLogEntryNarrow_t*)memLog)[currentIndex].addr = ptr;
return ptr;
}
else
{
if (currentMemLogWriteIndex >= MEMLOG_SIZE/6 )
{
loggingEnabled = false;
rd_write_text( "Allocation Logging is complete and DISABLED!\r\n\r\n");
}
// advance the read index if necessary.
if ( currentMemLogReadIndex == currentMemLogWriteIndex )
{
currentMemLogReadIndex++;
if ( currentMemLogReadIndex == MEMLOG_SIZE/6 )
{
currentMemLogReadIndex = 0;
}
}
((MemLogEntryWide_t*)memLog)[currentIndex].caller = (void *)(temp[0] - 4);
((MemLogEntryWide_t*)memLog)[currentIndex].prev_caller = (void *)*addr;
NU_Local_Control_Interrupts(savedInterruptState);
((MemLogEntryWide_t*)memLog)[currentIndex].taskid = (void *)TCD_Current_Thread;
((MemLogEntryWide_t*)memLog)[currentIndex].size = size;
((MemLogEntryWide_t*)memLog)[currentIndex].flags = 1; //allocated
((MemLogEntryWide_t*)memLog)[currentIndex].timestamp = *(volatile uint32_t *)0xfffbc410; // for arm9
//Standard operator
if (size == 0) size = 1;
void * ptr;
ptr = malloc(size);
((MemLogEntryWide_t*)memLog)[currentIndex].addr = ptr;
return ptr;
}
}
else
{
//Standard operator
if (size == 0) size = 1;
void * ptr;
ptr = malloc(size);
return ptr;
}
}
//#pragma CODE_SECTION ("section_ramset1_0")
void ::operator delete(void *ptr)
{
uint32_t savedInterruptState;
uint32_t currentIndex;
asm(" STR R14, [R13, #0xC]"); //save stack address temp[0]
asm(" STR R13, [R13, #0x10]"); //save pc return address temp[1]
if ( loggingEnabled )
{
savedInterruptState = NU_Local_Control_Interrupts(NU_DISABLE_INTERRUPTS);
// Note that this code is FRAGILE. It peeks backwards on the stack to find the return
// address of the caller. The location of the return address on the stack can be easily changed
// as a result of other changes in this function (i.e. adding local variables, etc).
// The offsets may need to be adjusted if this function is touched.
volatile unsigned int temp[2];
unsigned int *addr = (unsigned int *)temp[0] - 1;
unsigned int count = 1 + (0x20/4); //current stack space ***
//Scan for previous store
while ((*addr & 0xFFFF0000) != 0xE92D0000)
{
if ((*addr & 0xFFFFF000) == 0xE24DD000)
{
//add offset in words
count += ((*addr & 0xFFF) >> 2);
}
addr--;
}
count += MEM_bitLookupTable[*addr & 0xF];
count += MEM_bitLookupTable[(*addr >>4) & 0xF];
count += MEM_bitLookupTable[(*addr >> 8) & 0xF];
count += MEM_bitLookupTable[(*addr >> 12) & 0xF];
addr = (unsigned int *)temp[1] + count;
// FRAGILE CODE ENDS HERE
currentIndex = currentMemLogWriteIndex;
currentMemLogWriteIndex++;
if ( memLogNarrow )
{
if ( currentMemLogWriteIndex >= MEMLOG_SIZE/2 )
{
loggingEnabled = false;
rd_write_text( "Allocation Logging is complete and DISABLED!\r\n\r\n");
}
// advance the read index if necessary.
if ( currentMemLogReadIndex == currentMemLogWriteIndex )
{
currentMemLogReadIndex++;
if ( currentMemLogReadIndex == MEMLOG_SIZE/2 )
{
currentMemLogReadIndex = 0;
}
}
NU_Local_Control_Interrupts(savedInterruptState);
// finish logging the fields. these are thread safe so they dont need to be inside the protected section.
((MemLogEntryNarrow_t*)memLog)[currentIndex].addr = ptr;
((MemLogEntryNarrow_t*)memLog)[currentIndex].size = 0;
((MemLogEntryNarrow_t*)memLog)[currentIndex].flags = 2; //unallocated
}
else
{
((MemLogEntryWide_t*)memLog)[currentIndex].caller = (void *)(temp[0] - 4);
((MemLogEntryWide_t*)memLog)[currentIndex].prev_caller = (void *)*addr;
if ( currentMemLogWriteIndex >= MEMLOG_SIZE/6 )
{
loggingEnabled = false;
rd_write_text( "Allocation Logging is complete and DISABLED!\r\n\r\n");
}
// advance the read index if necessary.
if ( currentMemLogReadIndex == currentMemLogWriteIndex )
{
currentMemLogReadIndex++;
if ( currentMemLogReadIndex == MEMLOG_SIZE/6 )
{
currentMemLogReadIndex = 0;
}
}
NU_Local_Control_Interrupts(savedInterruptState);
// finish logging the fields. these are thread safe so they dont need to be inside the protected section.
((MemLogEntryWide_t*)memLog)[currentIndex].addr = ptr;
((MemLogEntryWide_t*)memLog)[currentIndex].size = 0;
((MemLogEntryWide_t*)memLog)[currentIndex].flags = 2; //unallocated
((MemLogEntryWide_t*)memLog)[currentIndex].taskid = (void *)TCD_Current_Thread;
((MemLogEntryWide_t*)memLog)[currentIndex].timestamp = *(volatile uint32_t *)0xfffbc410; // for arm9
}
//Standard operator
if (ptr != NULL) {
free(ptr);
}
}
else
{
//Standard operator
if (ptr != NULL) {
free(ptr);
}
}
}