释放嵌入式应用程序中的内存无助于减少虚拟存储
Freeing memory in an embedded application won't help in reducing virtual storage
我安装的嵌入式Linux系统有28K RAM和31.6M闪存。我开发了一个需要在嵌入式Linux中连续运行的应用程序。问题是应用程序的虚拟存储大小(top
命令中的VSZ)一直在增加,直到系统崩溃。如果我理解正确并纠正我的错误,VSZ应该根据程序所做的内存分配而变化,如果内存被释放,它应该恢复到以前的值并保持不变。
该程序在源代码中使用以下声明:
1-结构指针的矢量:
vector<Struct*> someVector; // Struct pointers are initialized with new
// After the previous vector has some values, it is freed like this
for(unsigned i = 0; i < someVector.size(); i++)
{
delete someVector[i];
}
someVector.clear();
vector<Struct*>().swap(someVector);
2-字符串的矢量,与以前相同,但不是循环中的delete
:someVector[i] = "";
3-char*
char* somePointer = (char*) malloc(100);
free(somePointer);
somePointer = NULL;
4-有时我使用用new
初始化的fstream*
,我认为这不会有任何区别,因为C++对象一旦超出范围就会被销毁。
5-char** array = new char*[100];
这被delete[] array
删除。我在内部元素上使用了delete
,但valgrind
给了我Mismatched free/delete
或类似的东西。
注意:源代码很大,这些是应用程序使用最多的数据结构。如果有任何其他可疑的事情,我会更新
我使用SSH编译应用程序并将其移动到嵌入式设备,运行应用程序并监控top
命令输出;应用程序进程的VSZ值一直在增加,直到像11K这样的大值和系统崩溃。我确信我所做的每一次分配都有相应的空闲机制(free, delete
等)。
valgrind ./myApplication
工具甚至没有显示警告消息,我应该假设分配和释放是安全完成的吗?
感谢您的帮助。我可以立即获得任何需要的信息。提前感谢!
更新8/4/2015:增加应用程序VSZ的过程是不断收集数据并将其存储在闪存上的文件中,有一种机制可以检查是否超过大小,但我现在不使用它。这可能有关系吗?
绝对没有理由期望delete/free将虚拟内存返回到系统——他们通常会将其保留在进程中,以便以后重用。一些分配模式将导致增长,即使由于免费存储碎片而没有泄漏。
第一步仍然是确保没有泄漏,既可以使用valgrind,也可以在可能的情况下在智能指针控制下移动这些动态分配,还可以使用valgrind的massif工具查看分配的内存去向(这将有助于识别luk32提到的问题)。
如果仍然需要的话,下一步是使用专门的分配器:固定大小的对象分配器(消除碎片并最大限度地减少开销),用于具有已知生存期的对象(无论大小)的竞技场分配器,以及用于显式、确定性地将VM返回到操作系统的基于mmap的后备存储。
请注意,您确实有一个内置的arena分配器可用——它用于具有自动作用域的局部变量。使用它而不是new
——在适用的情况下——可以让生活变得更简单。
someVector[i] = "";
这并不一定意味着内部缓冲区将被修剪。你可以用capacity()
来检查它。在c++11中有shrink_to_fit
,其他方法似乎不起作用。
#include <iostream>
using namespace std;
int main() {
string s("Some example string. Let's give it few more bytes.");
cout << s.size() << 'n';
cout << s.capacity() << 'n';
s = "";
cout << s.capacity() << 'n';
s.clear();
cout << s.capacity() << 'n';
s.resize(0);
cout << s.capacity() << 'n';
s.shrink_to_fit();
cout << s.capacity() << 'n';
return 0;
}
为除shrink_to_fit
之外的所有方法提供50
,在ideone上:http://ideone.com/nwIzYz.valgrind
也不会将其报告为"丢失"。因此,在删除这些对象之前,它们将保留在内部缓冲区中。如果您在某个全局范围内使用它,然后尝试通过这些调用释放内存,那么它很可能无法工作。
New/delete
内部使用malloc/free
。这两个函数都是像mmap
或bkr/sbrk
(在linux上)这样的内核函数的包装器。这些函数跟踪页面,以便在完成大量小分配的情况下优化内存碎片。
当你调用free
时,这些页面可能不会返回到操作系统,就像你查询操作系统的内存时一样,操作系统不会给你内存,直到内存被使用或看起来你要使用它。
如果您想将内存返回到操作系统,在linux上,可以使用malloc_trim。
我在c++03编译器上使用了这种方法来缩小大小。
template<typename T, class Allocator>
void shrink_capacity(std::vector<T,Allocator>& m)
{
std::vector<T,Allocator>(m.begin(),m.end()).swap(m);
}
- 用于创建/注册虚拟存储设备的 IOKit 驱动程序
- MOVNTI 存储是否相对于由同一线程创建的其他 MOVNTI 存储重新排序?
- 是否有任何模式等效于虚拟模板功能?
- 为什么使用存储在虚拟方法表中的地址调用虚拟函数的函数会返回垃圾?
- 将对象存储为其基本虚拟类
- 虚拟函数在哪里使用 vpointer to vtable 来解析方法调用,非虚拟方法存储在哪里以及如何解析它们?
- 我可以在 ANTLR4 中使用类似于 c++ 的虚拟令牌(具有相同返回值的令牌)吗?
- Windows TPM 虚拟智能卡 RSA 密钥存储
- C++ ->尝试逐字阅读一行文本。如何使指针等效于用于存储输入的当前二维数组
- c++依赖于派生类的纯虚拟函数
- 为什么我们没有适用于所有类型的偏移量(具有虚拟继承的类型除外)?
- 具有自动存储持续时间的虚拟功能似乎不起作用
- 释放嵌入式应用程序中的内存无助于减少虚拟存储
- c++将对纯虚拟类的引用存储为类的成员
- 将临时对象保留在寄存器上以避免虚拟机中的额外存储/加载
- 虚拟方法表在C++中存储在哪里
- 虚拟方法不作用于虚拟
- 如何在C++中创建虚拟存储空间
- 创建自己的输出存储而不是应用于现有存储的c++算法
- 类似于虚拟成员(结构)的东西