我正在使用CFNetwork API来检测OS代理设置。我的设置主要基于此: https://github.com/adobe/chromium/blob/master/net/proxy/proxy_resolver_mac.cc 几乎与此相同: https://developer.apple.com/library/archive/samplecode/CFProxySupportTool/Introduction/Intro.html
我使用CFNetworkCopyProxiesForURL来获取代理列表,对于PAC类型,使用CFNetworkExecuteProxyAutoConfigurationURL来获取并执行PAC脚本,立即在当前线程上运行运行循环,而该线程已经不在ui线程上。>
这一切都正常工作,并且我已仔细检查以确保我遵循创建规则以正确发布结果。但是,当使用Xcode工具时,我看到_CFNetworkExecuteProxyAutoConfigurationURLDelegated泄漏到PAC :: PACClient的std :: shared_ptrs。由于该对象从未暴露给我,因此我不确定如何控制它的释放,但它正在泄漏。这只是获取PAC文件的问题,显式代理不会泄漏。我曾尝试在所有CFDictionaries上添加冗余CFRelease调用,然后向我公开这些调用以查看是否保留了某些内容,但这对PACClient泄漏没有任何影响。
在Mac上的ARC项目中,它是cpp文件而不是目标C。
有人遇到过这种泄漏并且知道如何预防吗?
下面是执行查找的代码段,与上述项目的步骤相同。
struct PACRequestInfo {
CFURLRef url; // Caller gets this from a dictionary, doesn't need release
CFURLRef scriptURL; // Caller gets this from a dictionary, doesn't need release
CFMutableArrayRef proxies; // Reference to a dictionary that is released by the caller
};
void resultCallback(void* client, CFArrayRef proxies, CFErrorRef error) {
// Error handling removed for brevity
if (CFTypeRef* resultPtr = (CFTypeRef*) client)
*resultPtr = CFRetain(proxies);
CFRunLoopStop(CFRunLoopGetCurrent());
}
// Provided PACRequestInfo is created on the stack by the caller
void doPACRequest(const PACRequestInfo& info) {
CFTypeRef result = nullptr;
CFStreamClientContext context = { 0, &result, nullptr, nullptr, nullptr };
// Scoped ptr not shown but just calls CFRelease on destruction
CFScopedPtr<CFRunLoopSourceRef> runLoopSource(CFNetworkExecuteProxyAutoConfigurationURL(info.scriptURL, info.url, resultCallback, &context));
if (runLoopSource) {
const static CFStringRef kPrivateRunLoopMode = CFSTR("myprivateloop");
CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kPrivateRunLoopMode);
CFRunLoopRunInMode(kPrivateRunLoopMode, 1.0e10, false);
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), runLoopSource, kPrivateRunLoopMode);
if (result && CFGetTypeID(result) == CFArrayGetTypeID()) {
CFArrayRef resultArray = (CFArrayRef) result;
CFArrayAppendArray(info.proxies, resultArray, CFRangeMake(0, CFArrayGetCount(resultArray)));
}
}
// Retain was called on this value during ResultCallback.
if (result) {
CFRelease(result);
}
}