【发布时间】:2017-03-30 19:59:35
【问题描述】:
我正在努力解决与可可基金会内存管理相关的一个问题。基本上我有一个项目,用 Rust 编写,我使用 cocoa-rs 和 objc-rs 与 Objective-C 交互。我熟悉 CoreFoundation 和 CocoaFoundation 中的内存管理(我已经阅读了文档中的相应文章)。当我使用 CoreFoundation 函数时,我没有任何内存问题,但是当我使用 CocoaFoundation 相关的东西时,我遇到了很多问题,似乎从 CocoaFoundation 获取任何对象都会泄漏内存。
这是导致记忆记忆的功能之一的简化版本:
pub fn enumerate_apps()-> Vec<Rc<AppInfo>> {
let mut apps_list = Vec::new();
unsafe {
let shared_workspace: *mut Object = msg_send![class("NSWorkspace"), sharedWorkspace];
let running_apps: *mut Object = msg_send![shared_workspace, runningApplications];
let apps_count = msg_send![running_apps, count];
for i in 0..apps_count {
let app: *mut Object = msg_send![running_apps, objectAtIndex:i];
// Those ones are not used at the moment, but I actually need them,
// I just removed all business logic to keep the example simple and compilable
// to demonstrate the problem.
let bundle_url: *mut Object = msg_send![app, bundleURL];
let app_bundle: *mut Object = msg_send![class("NSBundle"), bundleWithURL:bundle_url];
let info_dict: *mut Object = msg_send![app_bundle, infoDictionary];
apps_list.push(Rc::new(AppInfo {
pid: msg_send![app, processIdentifier],
}));
}
}
apps_list
}
我尝试在循环中调用此函数以使内存泄漏可见:
fn main() {
loop {
for i in 0..200 {
enumerate_apps();
}
std::thread::sleep(std::time::Duration::from_millis(5000));
}
}
当我运行应用程序时,我可以看到随着时间的推移它消耗的内存越来越多。
我的问题是:为什么?在这样的 FFI 代码中管理内存的正确方法是什么?如果我在 XCode 中使用普通的 Objective-C 运行相同的代码,它可以正常工作并且似乎不会泄漏内存。嗯,XCode中之所以不泄露内存,是因为默认启用了ARC。据我所知,当我们以这种方式使用 Rust 的 Objective-C 时,ARC 并没有启用,所以基本上这意味着我们必须自己管理内存。注释包含bundle_url、app_bundle、info_dict 的 3 行会造成内存泄漏消失的错觉(不注释它们,进程每 2 秒泄漏几兆字节的内存),但实际上内存仍然泄漏,但没那么快。
我尝试了什么:
- 我尝试在函数的开头创建一个
NSAutoreleasePool,并在创建时为bundle_url和app_bundle调用autorelease()。没用,内存还是泄露了。 - 我尝试在
bundle_url和app_bundle上手动调用release(),没有任何效果。 - 甚至尝试在他们身上拨打
dealloc()(我认为这是错误的方式),这也无助于解决我的问题。
我做错了吗?还是objc-rs 中的错误(我想这不太可能,但谁知道)?
【问题讨论】:
标签: objective-c cocoa rust ffi