我在 pic32 处理器上使用 malloc()/free() 和朋友,所以没有虚拟内存等等,只是我在链接时声明的固定大小的堆。有什么方法可以在运行时确定我目前 malloc 了多少?还有多少可用?我见过一些对 mallinfo() 函数的引用,但当前的 pic32 库似乎不支持它。
问问题
3851 次
2 回答
3
我已经使用了 PIC18 和 PIC24 处理器,并且发现堆要谨慎使用。malloc()
一个技巧是在设备启动时,通过使用越来越大的内存块来确定堆大小,free()
直到找到限制。然后,您可以自行跟踪分配的内存。
注意事项:
- 如果您分配/取消分配奇数或大块内存,所有赌注都
malloc()
将失败,如果您碰巧有足够的可用内存字节,但不在连续块中,则会失败。 malloc()
如果您使用使用/的第三方代码,free()
您还必须查看/修改他们的代码。
我发现可以在堆上完成的任何事情都可以通过静态内存或堆栈完成,但代价是重构代码。这对你来说是一个可行的选择吗?
于 2012-11-30T18:13:22.260 回答
0
下面是为 Arduino 编写的内存分析器。它取自Arduino 论坛中的帖子。您将需要进行必要的修改以使其在 PIC 中正常工作。但它应该能够帮助您确定运行时的内存使用情况。
/*
* Cut-and-pasted from www.arduino.cc playground section for determining heap and stack pointer locations.
* http://www.arduino.cc/playground/Code/AvailableMemory
*
* Also taken from the Pololu thread from Paul at: http://forum.pololu.com/viewtopic.php?f=10&t=989&view=unread#p4218
*
* Reference figure of AVR memory areas .data, .bss, heap (all growing upwards), then stack growing downward:
* http://www.nongnu.org/avr-libc/user-manual/malloc.html
*
*/
extern unsigned int __data_start;
extern unsigned int __data_end;
extern unsigned int __bss_start;
extern unsigned int __bss_end;
extern unsigned int __heap_start;
//extern void *__malloc_heap_start; --> apparently already declared as char*
//extern void *__malloc_margin; --> apparently already declared as a size_t
extern void *__brkval;
// RAMEND and SP seem to be available without declaration here
int16_t ramSize=0; // total amount of ram available for partitioning
int16_t dataSize=0; // partition size for .data section
int16_t bssSize=0; // partition size for .bss section
int16_t heapSize=0; // partition size for current snapshot of the heap section
int16_t stackSize=0; // partition size for current snapshot of the stack section
int16_t freeMem1=0; // available ram calculation #1
int16_t freeMem2=0; // available ram calculation #2
/* This function places the current value of the heap and stack pointers in the
* variables. You can call it from any place in your code and save the data for
* outputting or displaying later. This allows you to check at different parts of
* your program flow.
* The stack pointer starts at the top of RAM and grows downwards. The heap pointer
* starts just above the static variables etc. and grows upwards. SP should always
* be larger than HP or you'll be in big trouble! The smaller the gap, the more
* careful you need to be. Julian Gall 6-Feb-2009.
*/
uint8_t *heapptr, *stackptr;
uint16_t diff=0;
void check_mem() {
stackptr = (uint8_t *)malloc(4); // use stackptr temporarily
heapptr = stackptr; // save value of heap pointer
free(stackptr); // free up the memory again (sets stackptr to 0)
stackptr = (uint8_t *)(SP); // save value of stack pointer
}
/* Stack and heap memory collision detector from: http://forum.pololu.com/viewtopic.php?f=10&t=989&view=unread#p4218
* (found this link and good discussion from: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1213583720%3Bstart=all )
* The idea is that you need to subtract your current stack pointer (conveniently given by the address of a local variable)
* from a pointer to the top of the static variable memory (__bss_end). If malloc() is being used, the top of the heap
* (__brkval) needs to be used instead. In a simple test, this function seemed to do the job, showing memory gradually
* being used up until, with around 29 bytes free, the program started behaving erratically.
*/
//extern int __bss_end;
//extern void *__brkval;
int get_free_memory()
{
int free_memory;
if((int)__brkval == 0)
free_memory = ((int)&free_memory) - ((int)&__bss_end);
else
free_memory = ((int)&free_memory) - ((int)__brkval);
return free_memory;
}
void setup() // run once, when the sketch starts
{
Serial.begin(57600);
}
void loop() // run over and over again
{
Serial.print("\n\n--------------------------------------------");
Serial.print("\n\nLOOP BEGIN: get_free_memory() reports [");
Serial.print( get_free_memory() );
Serial.print("] (bytes) which must be > 0 for no heap/stack collision");
Serial.print("\n\nSP should always be larger than HP or you'll be in big trouble!");
check_mem();
Serial.print("\nheapptr=[0x"); Serial.print( (int) heapptr, HEX); Serial.print("] (growing upward, "); Serial.print( (int) heapptr, DEC); Serial.print(" decimal)");
Serial.print("\nstackptr=[0x"); Serial.print( (int) stackptr, HEX); Serial.print("] (growing downward, "); Serial.print( (int) stackptr, DEC); Serial.print(" decimal)");
Serial.print("\ndifference should be positive: diff=stackptr-heapptr, diff=[0x");
diff=stackptr-heapptr;
Serial.print( (int) diff, HEX); Serial.print("] (which is ["); Serial.print( (int) diff, DEC); Serial.print("] (bytes decimal)");
Serial.print("\n\nLOOP END: get_free_memory() reports [");
Serial.print( get_free_memory() );
Serial.print("] (bytes) which must be > 0 for no heap/stack collision");
// ---------------- Print memory profile -----------------
Serial.print("\n\n__data_start=[0x"); Serial.print( (int) &__data_start, HEX ); Serial.print("] which is ["); Serial.print( (int) &__data_start, DEC); Serial.print("] bytes decimal");
Serial.print("\n__data_end=[0x"); Serial.print((int) &__data_end, HEX ); Serial.print("] which is ["); Serial.print( (int) &__data_end, DEC); Serial.print("] bytes decimal");
Serial.print("\n__bss_start=[0x"); Serial.print((int) & __bss_start, HEX ); Serial.print("] which is ["); Serial.print( (int) &__bss_start, DEC); Serial.print("] bytes decimal");
Serial.print("\n__bss_end=[0x"); Serial.print( (int) &__bss_end, HEX ); Serial.print("] which is ["); Serial.print( (int) &__bss_end, DEC); Serial.print("] bytes decimal");
Serial.print("\n__heap_start=[0x"); Serial.print( (int) &__heap_start, HEX ); Serial.print("] which is ["); Serial.print( (int) &__heap_start, DEC); Serial.print("] bytes decimal");
Serial.print("\n__malloc_heap_start=[0x"); Serial.print( (int) __malloc_heap_start, HEX ); Serial.print("] which is ["); Serial.print( (int) __malloc_heap_start, DEC); Serial.print("] bytes decimal");
Serial.print("\n__malloc_margin=[0x"); Serial.print( (int) &__malloc_margin, HEX ); Serial.print("] which is ["); Serial.print( (int) &__malloc_margin, DEC); Serial.print("] bytes decimal");
Serial.print("\n__brkval=[0x"); Serial.print( (int) __brkval, HEX ); Serial.print("] which is ["); Serial.print( (int) __brkval, DEC); Serial.print("] bytes decimal");
Serial.print("\nSP=[0x"); Serial.print( (int) SP, HEX ); Serial.print("] which is ["); Serial.print( (int) SP, DEC); Serial.print("] bytes decimal");
Serial.print("\nRAMEND=[0x"); Serial.print( (int) RAMEND, HEX ); Serial.print("] which is ["); Serial.print( (int) RAMEND, DEC); Serial.print("] bytes decimal");
// summaries:
ramSize = (int) RAMEND - (int) &__data_start;
dataSize = (int) &__data_end - (int) &__data_start;
bssSize = (int) &__bss_end - (int) &__bss_start;
heapSize = (int) __brkval - (int) &__heap_start;
stackSize = (int) RAMEND - (int) SP;
freeMem1 = (int) SP - (int) __brkval;
freeMem2 = ramSize - stackSize - heapSize - bssSize - dataSize;
Serial.print("\n--- section size summaries ---");
Serial.print("\nram size=["); Serial.print( ramSize, DEC ); Serial.print("] bytes decimal");
Serial.print("\n.data size=["); Serial.print( dataSize, DEC ); Serial.print("] bytes decimal");
Serial.print("\n.bss size=["); Serial.print( bssSize, DEC ); Serial.print("] bytes decimal");
Serial.print("\nheap size=["); Serial.print( heapSize, DEC ); Serial.print("] bytes decimal");
Serial.print("\nstack size=["); Serial.print( stackSize, DEC ); Serial.print("] bytes decimal");
Serial.print("\nfree size1=["); Serial.print( freeMem1, DEC ); Serial.print("] bytes decimal");
Serial.print("\nfree size2=["); Serial.print( freeMem2, DEC ); Serial.print("] bytes decimal");
delay(3000);
}
不是一个精确的解决方案,但它应该作为一个很好的起点。
于 2012-12-03T15:18:05.033 回答