mnn版本为2.7.0的静态库在windows平台内存异常问题
具体的堆栈信息如下: CONTEXT: (.ecxr) eax=000000e5 ebx=47031e2c ecx=00000008 edx=595a854a esi=00000100 edi=47031e1c eip=3e7b37a4 esp=42d2e7cc ebp=42d2e858 iopl=0 nv up ei pl nz na po nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010202 nce_alg!MNNC3ToFloatRGBA+0x34: 3e7b37a4 f30f1141f8 movss dword ptr [ecx-8],xmm0 ds:002b:00000000=???????? Resetting default scope
EXCEPTION_RECORD: (.exr -1) ExceptionAddress: 3e7b37a4 (nce_alg!MNNC3ToFloatRGBA+0x00000034) ExceptionCode: c0000005 (Access violation) ExceptionFlags: 00000000 NumberParameters: 2 Parameter[0]: 00000001 Parameter[1]: 00000000 Attempt to write to address 00000000
PROCESS_NAME: Yealink Meeting.exe
WRITE_ADDRESS: 00000000
ERROR_CODE: (NTSTATUS) 0xc0000005 - 0x%p 0x%p %s
EXCEPTION_CODE_STR: c0000005
EXCEPTION_PARAMETER1: 00000001
EXCEPTION_PARAMETER2: 00000000
STACK_TEXT:
42d2e858 3e76f7bc 42d2e884 42d2e878 118dbac8 nce_alg!MNNC3ToFloatRGBA+0x34
42d2e89c 3e76f50c 406b4648 406b4258 406b4648 nce_alg!MNN::CV::ImageProcess::convert+0x24c
42d2e928 3e74fd93 4911fea0 00000140 000000b4 nce_alg!MNN::CV::ImageProcess::convert+0x1ec
从解析及分析定位的结论看看是在函数MNNC3ToFloatRGBA函数中出现了空bufffer,应该是在函数的source和dest指针,但不能定位为何出现这个问题,我看源代码中source和dest指针是通过下面代码实现的
std::unique_ptr<Tensor> input(createImageTensor(halide_type_of<uint8_t>(), iw, ih, ic, (void*)source)),
output(createImageTensor(type, ow, oh, oc, dest));
目前只能分析这里,还请教大佬帮忙看看,谢谢。
这个看着是 dest 为空,检查下 convert 的目标指针是否为空吧
目标指针已经有判空。
已经对dest指针做判空处理,但还是出现。 if(NULL == kv.second) return NCE_FAILED;
MNN::Tensor *pTensor = kv.second;
NCE_S32 pWidth = pTensor->width();
NCE_S32 pHeight = pTensor->height();
NCE_S32 pChn = pTensor->channel();
NCE_S32 imgSz = pWidth * pHeight;
NCE_U8 * data = (NCE_U8*)pTensor->host<void>();
if (data == NULL)
{
return NCE_FAILED;
}
...
pprocessors->convert(image_datas.image, image_datas.image_attr.u32Width, image_datas[count].image_attr.u32Height, 0, kv.second);
ErrorCode CPUImageProcess::onExecute(const std::vector<Tensor > &inputs, const std::vector<Tensor > &outputs) {
if (0 == mStride) {
mStride = iw * ic;
}
auto source = inputs[0]->host<uint8_t>();
void dest = nullptr;
CV::Point points[2];
auto destBytes = dtype.bytes();
int tileCount = UP_DIV(ow, CACHE_SIZE);
const int regions = nullptr;
if (draw) {
// change input to output
dest = source;
oh = inputs[1]->length(0);
ow = iw;
oc = ic;
destBytes = inputs[0]->getType().bytes();
// draw one
tileCount = 1;
// src is color
samplerDest = inputs[2]->host<uint8_t>();
// get region info ptr
regions = inputs[1]->host
if (nullptr == dest)
return INPUT_DATA_ERROR;
for (int i = 0; i < oh; ++i) {
int dy = draw ? regions[3 * i] : i;
auto dstY = (uint8_t*)dest + dy * destBytes * ow * oc;
for (int tIndex = 0; tIndex < tileCount; ++tIndex) {
int xStart = tIndex * CACHE_SIZE;
int count = std::min(CACHE_SIZE, ow - xStart);
if (draw) {
xStart = regions[3 * i + 1];
count = regions[3 * i + 2] - xStart + 1;
}
auto dstStart = dstY + destBytes * oc * xStart;
if (!blitFloat) {
blitDest = dstStart;
}
if (!blitter) {
samplerDest = blitDest;
}
// Sample
if (!draw) {
// Compute position
points[0].fX = xStart;
points[0].fY = dy;
points[1].fX = xStart + count;
points[1].fY = dy;
transform.mapPoints(points, 2);
float deltaY = points[1].fY - points[0].fY;
float deltaX = points[1].fX - points[0].fX;
int sta = 0;
int end = count;
// FUNC_PRINT(sta);
if (wrap == WrapType_ZERO) {
// Clip: Cohen-Sutherland
auto clip = _computeClip(points, iw, ih, transformInvert, xStart, count);
sta = clip.first;
end = clip.second;
points[0].fX = sta + xStart;
points[0].fY = dy;
transform.mapPoints(points, 1);
if (sta != 0 || end < count) {
if (ic > 0) {
if (sta > 0) {
::memset(samplerDest, paddingValue, ic * sta);
}
if (end < count) {
::memset(samplerDest + end * ic, paddingValue, (count - end) * ic);
}
} else {
// TODO, Only support NV12 / NV21
::memset(samplerDest, paddingValue, count);
::memset(samplerDest + count, 128, UP_DIV(count, 2) * 2);
}
}
}
points[1].fX = (deltaX) / (float)(count);
points[1].fY = (deltaY) / (float)(count);
sampler(source, samplerDest, points, sta, end - sta, count, iw, ih, mStride);
}
// Convert format
if (blitter) {
blitter(samplerDest, blitDest, count);
}
// Turn float
if (blitFloat) {
blitFloat(blitDest, (float*)dstStart, mean, normal, count);
上面是onExecute函数的代码,函数void MNNC3ToFloatRGBA(const unsigned char* source, float* dest, const float* mean, const float* normal, size_t count)中的dest指针是通过for循环遍历指针指代进行的,如果在convert中的dest为空,这在onExecute函数中就出现异常了。
Marking as stale. No activity in 60 days.