如何在C++; 在嵌入式环境中,检测C++内存泄漏的好方法是什么?我尝试重载新操作符来记录每个数据分配,但我一定是做错了什么,这种方法不起作用。还有其他人遇到过类似的情况吗
这是new和delete操作符重载的代码 编辑: 完全公开:我正在寻找我的程序中的内存泄漏,我正在使用其他人编写的代码来重载new和delete操作符。我的部分问题是我不完全理解它的作用。我知道目标是记录调用方和前一个调用方的地址、分配的大小,如果我们正在分配,则为1,如果我们正在解除分配,则为2。加上正在运行的线程的名称 感谢所有的建议,我将尝试一种工作人员建议的不同方法。如果它有效,我会把它贴在这里 再次感谢所有一流的程序员花时间回答问题 堆积如山的岩石 结论 谢谢你的回答。不幸的是,我不得不转向另一个更紧迫的问题。此次泄漏仅在极不可能的情况下发生。我觉得丢下它很糟糕,如果我有更多的时间,我可能会回去。我选择了最有可能使用的答案如何在C++; 在嵌入式环境中,检测C++内存泄漏的好方法是什么?我尝试重载新操作符来记录每个数据分配,但我一定是做错了什么,这种方法不起作用。还有其他人遇到过类似的情况吗,c++,memory-leaks,embedded,C++,Memory Leaks,Embedded,这是new和delete操作符重载的代码 编辑: 完全公开:我正在寻找我的程序中的内存泄漏,我正在使用其他人编写的代码来重载new和delete操作符。我的部分问题是我不完全理解它的作用。我知道目标是记录调用方和前一个调用方的地址、分配的大小,如果我们正在分配,则为1,如果我们正在解除分配,则为2。加上正在运行的线程的名称 感谢所有的建议,我将尝试一种工作人员建议的不同方法。如果它有效,我会把它贴在这里 再次感谢所有一流的程序员花时间回答问题 堆积如山的岩石 结论 谢谢你的回答。不幸的是,我不得
#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);
}
}
}
#包括
#包括“stdio.h”
#包括“nucleus.h”
#包括“plus/inc/dm_defs.h”
#包括“plus/inc/pm_defs.h”
#包括“posix\inc\posix.h”
外部无效*TCD\u当前线程;
外部“C”无效rd_写入文本(字符*文本);
外部PM_PCB*PMD_创建的\u池\u列表;
类型定义结构{
无效*地址;
uint16_t尺寸;
uint16_t标志;
}MemlogentryRown\t;
类型定义结构{
无效*地址;
uint16_t尺寸;
uint16_t标志;
无效*主叫人;
void*上一个调用者;
void*taskid;
uint32_t时间戳;
}MemLogEntryWide\u t;
//大小查找表
无符号字符MEM_bitLookupTable[]={
0,1,1,2,1,2,2,3,1,2,2,3,1,3,3,4
};
//#pragma代码段(“段段段段段段段段段段段段段段段段段段段段段段段段段段段段段段段段段段段段段段段段段段段段段段段段段段段段段段段段段段段段段段
void*::运算符new(无符号整数大小)
{
asm(“STR R14,[R13,#0xC]”;//保存堆栈地址temp[0]
asm(“STR R13[R13,#0x10]”;//保存pc返回地址temp[1]
如果(已启用日志记录)
{
uint32_t savedInterruptState;
uint32\u t当前索引;
//保护螺纹不安全部分。
savedInterruptState=NU_本地控制中断(NU_禁用中断);
//请注意,这段代码是脆弱的。它向后窥视堆栈以找到返回值
//调用方的地址。堆栈上返回地址的位置可以很容易地更改
//由于该函数中的其他更改(即添加局部变量等)。
//如果触摸此功能,可能需要调整偏移量。
易失性无符号整数温度[2];
无符号整数*地址=(无符号整数*)温度[0]-1;
无符号整数计数=1+(0x20/4);//当前堆栈空间***
//扫描以前的商店
而((*addr&0xFFFF0000)!=0xE92D0000)
{
如果((*addr&0xFFFFF000)==0xE24DD000)
{
//在单词中添加偏移量
计数+=(*addr&0xFFF)>>2);
}
地址--;
}
count+=MEM_bitLookupTable[*addr&0xF];
count+=MEM_bitLookupTable[(*addr>>4)和0xF];
count+=MEM_bitLookupTable[(*addr>>8)和0xF];
count+=MEM_bitLookupTable[(*addr>>12)和0xF];
地址=(无符号整数*)温度[1]+计数;
//脆弱的代码到此结束
currentIndex=currentMemLogWriteIndex;
currentMemLogWriteIndex++;
if(memlog窄)
{
如果(currentMemLogWriteIndex>=MEMLOG\u SIZE/2)
{
loggingEnabled=false;
rd_写入_文本(“分配日志记录已完成并已禁用!\r\n\r\n”);
}
//如有必要,提前读取索引。
如果(currentMemLogReadIndex==currentMemLogWriteIndex)
{
currentMemLogReadIndex++;
如果(currentMemLogReadIndex==MEMLOG\u SIZE/2)
{
currentMemLogReadIndex=0;
}
}
本地控制中断(保存中断状态);
//标准运算符
//(对于分区分析,我们必须考虑,如果我们将0的大小总是为1的大小,那么必须对分区进行优化)。
如果(尺寸=0)尺寸=1;
((memlogentryslown_t*)memLog)[currentIndex].size=size;
((memlogentryslown\u t*)memLog)[currentIndex].flags=1;//已分配
//标准运算符
无效*ptr;
ptr=malloc(尺寸);
((memlogentryslown_t*)memLog)[currentIndex].addr=ptr;
返回ptr;
}
其他的
{
如果(currentMemLogWriteIndex>=MEMLOG\u SIZE/6)
{
loggingEnabled=false;
rd_写入_文本(“分配日志记录已完成并已禁用!\r\n\r\n”);
}
//如有必要,提前读取索引。
如果(currentMemLogReadIndex==currentMemLogWriteIndex)
{
currentMemLogReadIndex++;
如果(currentMemLogReadIndex==MEMLOG\u SIZE/6)
{
currentMemLogReadIndex=0;
}
}
((MemLogEntryWide_t*)memLog)[currentIndex]。调用者=(void*)(临时[0]-4);
((MemLogEntryWide_t*)memLog)[currentIndex].prev_caller=(void*)*addr;
本地控制中断(保存中断状态);
((MemLogEntryWide\u t*)memLog)[currentIndex].taskid=(void*)TCD\u Current\u Thread;
((MemLogEntryWide_t*)memLog)[currentIndex].size=size;
((MemLogEntryWide\u t*)memLog)[currentIndex].flags=1;//已分配
((MemLogEntryWide\u t*)memLog)[currentIndex]。时间戳=*(volatile uint32\u t*)0xfffbc410;//用于arm9
//标准运算符
如果(尺寸=0)尺寸=1;
无效*ptr;
ptr=malloc(尺寸);
((MemLogEntryWide)*
class SmartCoMem
{
public:
SmartCoMem() : m_size( 0 ), m_ptr64( 0 ) {
}
~SmartCoMem() {
if( m_size )
CoTaskMemFree((LPVOID)m_ptr64);
}
void copyin( LPCTSTR in, const unsigned short size )
{
LPVOID ptr;
ptr = CoTaskMemRealloc( (LPVOID)m_ptr64, size );
if( ptr == NULL )
throw std::exception( "SmartCoMem: CoTaskMemAlloc Failed" );
else
{
m_size = size;
m_ptr64 = (__int64)ptr;
memcpy( (LPVOID)m_ptr64, in, size );
}
}
std::string copyout( ) {
std::string out( (LPCSTR)m_ptr64, m_size );
return out;
}
__int64* ptr() {
return &m_ptr64;
}
unsigned short size() {
return m_size;
}
unsigned short* sizePtr() {
return &m_size;
}
bool loaded() {
return m_size > 0;
}
private:
//don't allow copying as this is a wrapper around raw memory
SmartCoMem (const SmartCoMem &);
SmartCoMem & operator = (const SmartCoMem &);
__int64 m_ptr64;
unsigned short m_size;
};
void *operator new (size_t);
void *operator new [] (size_t);
void *operator new (size_t, void *);
void *operator new [] (size_t, void *);
void *operator new (size_t, /* parameters of your choosing! */);
void *operator new [] (size_t, /* parameters of your choosing! */);
new
allocate memory
add entry to logging table
delete
check address exists in logging table
free memory
#define NEW new (__FILE__, __LINE__, __FUNCTION__)
void *operator new (size_t size, char *file, int line, char *function)
{
// log the allocation somewhere, no need to strcpy file or function, just save the
// pointer values
return malloc (size);
}
SomeObject *obj = NEW SomeObject (parameters);