本地c++库-谁必须释放内存以及如何释放
Native C++ library - who have to release the memory and how?
这是关于Android的。这句话的语境是:
c++库和java包装器类以及用于处理库中的c++类的本机函数(JNI)。当普通java代码需要c++对象时,它创建相应的java包装器对象,该包装器对象通过本机函数创建c++对象,并在'long'变量中记住指向本机对象的指针。在接下来的所有操作中,包装器将此指针指向本机函数等。
问题:
如何在最后释放所有分配的c++对象?目前每个包装类都有'finalize'方法,它调用本地函数来释放c++对象,但Android不保证调用'finalize'!另一方面,c++库通常不知道java代码分配了多少c++对象和什么类型的对象。
当我们的java应用程序终止时,剩余分配的内存会发生什么?当操作系统卸载本机库时,Android会自动释放从本机库使用的整个堆吗?
在进程生命周期结束时,所有进程内存(Java和c++堆)将被释放并由系统回收。但有一点是,Android活动关闭并不一定会结束这个过程。我不确定那里的进程关闭策略是什么。
另一方面,依赖于垃圾收集和finalize()对我来说听起来像是可靠的设计。你声称——"Android不保证finalize()
"。你有什么理由吗?因为如果它附带一个免责声明"当对象作为进程关闭的一部分被释放时…",那么我们仍然是好的。
如果您非常偏执,您可以编写自己的malloc()/free()/realloc()包装器,存储所有已分配对象的列表,并引入一个清除函数来遍历列表并释放所有对象。但是,包含Java对象的对象可能以一种奇怪的僵尸状态结束,在这种状态下,内存已经从它们下面释放出来了。这是一个很棘手的命题,很容易出错。所以我还是要说,要相信垃圾收集者。缺乏这些将是……不安。
由于范例的不同,您必须将显式销毁合并到使用c++资源在底层实现的Java对象中。所以是close()
或者其他类似的方法。同样的问题也出现在JNI中,所以这些问题的答案将适用于您:
强制Java调用c++析构函数(JNI)
至于关闭时的内存问题,在我看来,通常最好不要依赖它。如果你达到一个干净的状态,valgrind等可以确保你没有泄漏。
但是从技术的角度来看——因为Android是基于Linux的,我想它会做通常的事情,在进程关闭时释放所有的内存。利用这一点可以使您的程序退出比显式释放内存更快(仅对于使用其他方法来确保维护程序正确性并且在运行时不会泄漏的专家)。
我们正在使用jndi,我们遇到了这样的问题
实际上,问题在于我们重载了finalize()来完成清理。我们通过删除finalize()并创建clean()来解决问题。这个clean()调用执行适当删除操作的JNI函数(并将c++指针设置为空,以防万一)。我们调用clean()就像在c++中调用delete一样(例如,当变量超出作用域时)。
这对我们有用。我希望它对你有用。好运!
- 释放错误后堆使用
- G锁定铸造到基础上会释放模拟行为
- 在将变量声明为引用时,堆在释放后使用
- 在调用FreeLibrary后,释放动态链接到具有相同版本的CRT堆的DLL的内存
- 正在理解智能指针,但出现错误:未分配正在释放的指针
- C++双重释放或损坏(out)
- 如何在c++中释放内存
- 使用全局声明的向量时,C++双重释放错误/损坏
- 为什么这个 std::queue/指向结构的指针列表直到 List.Size() == 0 才释放内存?
- 为什么瓦尔格林德在不释放恶意内存后没有报告任何问题?
- 调用析构函数以释放动态分配的内存
- 在函数范围内在堆栈上分配的数组在离开函数时是否总是被释放?
- COM :是否可以查看是否存在对我的某个 COM 对象的进程外引用?我可以释放它吗?
- 如何在向量中释放指针?
- std::unordered_map析构函数不释放内存?
- 在C++中释放内存期间,迭代器与指针有何不同
- 包含矢量指针的结构的内存释放问题
- C++:在被本地字符串捕获后释放或销毁 malloc'd char *?
- 错误:malloc:对象 0x7f9edf504080 的 *** 错误:未分配正在释放的指针
- 如果分配数组引发异常,是否应该释放该数组