我有一个用于iPadOS的DriverKit驱动程序.它工作得很好,但静态分析器正在标记一个我不理解的可能的泄漏.标记的代码位于驱动程序类本身中:
void IMPL(CDCDriver, ReadComplete)
{
// Simply trampolines back to USBCDCInterface where the read is actually handled
IOBufferMemoryDescriptor *readDataBuffer = ivars->cdcInterface->readData(status, actualByteCount, completionTimestamp);
if (actualByteCount > 0) {
os_log(OS_LOG_DEFAULT, "[Driver] Got %u bytes of data!", actualByteCount);
if (ivars->client != nullptr) {
ivars->client->dataWasReceived(readDataBuffer, actualByteCount);
}
}
} // [!] Potential leak of an object stored into 'readDataBuffer'
根据分析器,在方法的第一行调用readData()
返回类型为IOBufferMemoryDescriptor
的OSObject
,保留计数为+1.但是,该方法是这样实现的:
IOBufferMemoryDescriptor *USBCDCInterface::readData(IOReturn status,
uint32_t actualByteCount,
uint64_t completionTimestamp)
{
pollForData();
return readDataBuffer;
}
这里,readDataBuffer
是USBCDCInterface
的成员变量,在驱动程序通过调用IOUSBHostInterface::CreateIOBuffer()
启动时创建:
IOBufferMemoryDescriptor *readDataBuffer = nullptr;
result = dataInterface->CreateIOBuffer(kIOMemoryDirectionIn, 256, &readDataBuffer);
if (result != kIOReturnSuccess) {
return result;
}
this->readDataBuffer = readDataBuffer;
我对OSObject
(及其子类)的理解是,它使用的引用计数机制非常类似于NSObject
.创建它,例如使用CreateIOBuffer()
,应该会产生一个保留计数为+1的对象.创建它的USBCDCInterface
实例拥有它,因此当它处理完它时应该是release()
(在USBCDCInterface::free()
中).简单地从readData()
返回它不应该转移所有权,释放它也不应该是该方法的调用者的责任.值得注意的是,在CDCDriver::ReadComplete()
的末尾对对象调用release()
会导致驱动程序崩溃,正如我所预期的那样,这让我认为这是分析器的假阳性.
要么我的理解有缺陷,从USBCDCInterface::readData()
返回该对象的某些方面(按照惯例或其他方式)迫使调用者释放它(尽管这样做会再次导致驱动程序崩溃),要么这是分析器部分的错误肯定.
如果这是objc/cocoa,我猜可能是我的方法的命名导致分析器假定readData()
方法有效地转移了所有权(就像-copy
或+alloc
方法),但是我找不到任何这样的命名约定的文档,我也不能弄清楚OSObject
方法是否/如何用它们的内存管理语义进行注释.
有没有人能提供一些见解?