我在intel Xscale设备上运行我的c ++应用程序。问题是,当我使用Valgrind运行我的应用程序offtarget(Ubuntu)时,它不会显示任何内存泄漏。
但是当我在目标系统上运行它时,它以50K可用内存开始,并在一夜之间减少到2K。如何捕捉这种泄漏,这是Valgrind没有显示的?
答案 0 :(得分:10)
这些小型嵌入式deviecs的常见罪魁祸首是内存碎片。您的应用程序可能在两个对象之间有可用内存。对此最常见的解决方案是为最常见的类使用专用分配器(C ++中的operator new)。纯粹用于大小为N的对象的内存池不会碎片化 - 两个对象之间的空间总是N的倍数。
答案 1 :(得分:3)
这可能不是泄漏,而只是运行时堆不向操作系统释放内存。这也可能是碎片化。
克服这个问题的可能方法:
分成两个应用程序。主应用程序将具有简单的逻辑,很少或没有动态内存使用。它将启动worker应用程序实际上以这样的块工作,即worker应用程序不会耗尽内存并定期重启该应用程序。这样,内存会定期返回给操作系统。
编写自己的内存分配器。例如,您可以分配专用堆并仅从那里分配内存,然后完全释放专用堆。这要求操作系统支持多个堆。
另请注意,您的程序可能在Ubuntu和目标系统上运行不同,因此会采用不同的执行路径,导致内存泄漏的代码在目标系统上执行,但不会在Ubuntu上执行。
答案 2 :(得分:3)
它可能不是实际的内存泄漏,但可能是内存使用量增加的情况。例如,它可能会分配一个不断增加的字符串:
string s;
for (i=0; i<n; i++)
s += "a";
50k并不是那么多,也许你应该手工检查你的来源,看看可能导致这个问题的原因。
答案 3 :(得分:1)
这听起来像碎片。碎片是由您在堆栈上分配对象引起的,例如:
object1
Object2的
object3
object4
然后删除一些对象
object1
object3
object4
你现在在内存中有一个未使用的洞。如果你为孔分配另一个太大的物体,那么这个孔将会被浪费掉。最终,如果有足够的内存流失,你可能会遇到很多漏洞而浪费你的记忆。
解决这个问题的方法是先尝试决定你的记忆要求。如果你有特定的对象,你知道你正在创建许多对象,请尝试确保它们的大小相同。
您可以使用池来使分配对特定类更有效...或者至少让您更好地跟踪它,以便您可以了解正在发生的事情并提出一个好的解决方案。
这样做的一种方法是创建一个静态:
struct Slot
{
Slot() : free(true) {}
bool free;
BYTE data[20]; // you'll need to tune the value 20 to what your program needs
};
Slot pool[500]; // you'll need to pick a good pool size too.
在程序启动时预先创建池并预先分配它,使其与程序的最大需求一样大。您可能想要HeapAlloc它(或者您的操作系统中的等效文件,以便您可以控制它何时从应用程序启动中的某个位置出现)。
然后覆盖可疑类的new和delete运算符,以便它们从此向量返回槽。因此,您的对象将存储在此向量中。
您可以覆盖相同大小的类的new和delete,以放入此向量中。
为不同的对象创建不同大小的池。
首先去找最坏的罪犯。
之前我做过类似的事情,它解决了我在嵌入式设备上遇到的问题。我也使用了很多STL,所以我创建了一个自定义分配器(google for stl custom allocator - 有很多链接)。这对于我的程序使用的迷你数据库中存储的记录非常有用。
答案 4 :(得分:0)
如果您的内存使用率下降,我认为它不能被定义为内存泄漏。 你在哪里得到内存使用情况的报告?系统可能只是将程序的大部分内存用在虚拟内存中。
我可以补充的是,Valgrind在查找内存泄漏方面非常有效!
答案 5 :(得分:0)
另外,您确定在分析代码时,代码覆盖率是否足以覆盖可能在目标平台上执行的所有代码路径?
Valgrind肯定不会撒谎。正如已经指出的那样,这可能确实是运行时堆没有释放内存,但我认为不是这样。
答案 6 :(得分:0)
您是否正在使用任何复杂的技术来跟踪对象的范围..? 如果是的话,比valgrind不够聪明,虽然你可以尝试通过与valgrind设置xscale相关的选项
答案 7 :(得分:0)
大多数应用程序都显示了这样的内存使用模式:
如果您的应用程序的大小持续增加,您可能会遇到麻烦。如果它在一段时间内增加了sizze然后达到相对稳定的状态,你可能不会。
答案 8 :(得分:0)
您可以使用Valgrind的massif工具,它将显示分配最多内存的位置以及它随时间的演变情况。