使用cblas_ccopy为何会引发间歇性内存错误?
cblas_ccopy复制Float指针时出现随机内存错误? 尝试使用
cblas_ccopy将值从一个指针复制到另一个指针,但约三分之一的概率会出现malloc: *** error ... incorrect checksum for freed object错误,作为单元测试运行时错误为objc[44736]: autorelease pool page 0x7fecb903c000 corrupted;作为脚本运行时错误为incorrect checksum。已尝试在malloc_error_break设置断点但无法解读输出,直接传入sourceArray和destinationArray而非转换为原始指针也无效。
原测试代码:
import Accelerate func testCopy() { // set capacity let capacity: Int = 1000 // destination array let destinationArray = UnsafeMutablePointer<Float>.allocate(capacity: capacity) destinationArray.initialize(repeating: 0, count: capacity) // source array let sourceArray = UnsafeMutablePointer<Float>.allocate(capacity: capacity) sourceArray.initialize(repeating: 1, count: capacity) // copy values cblas_ccopy(Int32(capacity), UnsafeRawPointer(sourceArray), 1, UnsafeMutableRawPointer(destinationArray), 1) // check to see if values were copied for idx in 0..<capacity { print(idx, destinationArray[idx]) } } testCopy()
嘿,这个问题的核心是你踩了BLAS函数命名规则的坑!
BLAS函数的命名是有明确规则的:
- 前缀
c代表complex single-precision(单精度复数) - 前缀
s代表single-precision real(单精度实数)
你现在操作的是普通的Float(单精度实数)数组,但cblas_ccopy会把传入的内存当成Complex<Float>来处理——每个复数占2个Float的内存空间。当你传入capacity=1000时,函数会试图访问1000 * 2 = 2000个Float的内存,直接超出了你分配的1000个Float的空间范围,这就导致了堆内存越界破坏。而这种错误的触发是随机的(取决于当前内存布局),所以才会出现“约三分之一概率报错”的情况。
解决方法分两种情况:
如果你要复制的是普通Float数组
把cblas_ccopy换成对应实数的函数cblas_scopy即可:cblas_scopy(Int32(capacity), sourceArray, 1, destinationArray, 1)(这里不需要转成
UnsafeRawPointer,直接传Float指针就行,BLAS的Swift绑定已经做了适配)如果你确实要处理复数数组
那你需要把数组类型改成Complex<Float>,同时注意内存分配的容量(allocate(capacity:)是按元素个数算的,直接传1000就会分配2000个Float的空间):import Accelerate func testComplexCopy() { let capacity: Int = 1000 let destination = UnsafeMutablePointer<Complex<Float>>.allocate(capacity: capacity) destination.initialize(repeating: .init(real: 0, imaginary: 0), count: capacity) let source = UnsafeMutablePointer<Complex<Float>>.allocate(capacity: capacity) source.initialize(repeating: .init(real: 1, imaginary: 0.5), count: capacity) // 现在用cblas_ccopy就正确了 cblas_ccopy(Int32(capacity), source, 1, destination, 1) // 后续检查和内存释放... destination.deinitialize(count: capacity) destination.deallocate() source.deinitialize(count: capacity) source.deallocate() }
额外提示:内存泄漏问题
你的原代码里只分配了指针但没有释放,这会导致内存泄漏。在Swift中使用UnsafeMutablePointer时,记得在使用完成后调用deinitialize(count:)和deallocate():
// 在testCopy函数末尾添加: destinationArray.deinitialize(count: capacity) destinationArray.deallocate() sourceArray.deinitialize(count: capacity) sourceArray.deallocate()
内容的提问来源于stack exchange,提问作者ASDFQWERTY

