为什么我会破坏堆破坏我的位图类?这个内联汇编有问题吗?

时间:2013-06-19 17:56:52

标签: c++ memory memory-management assembly heap-corruption

我正在进行图像处理,并且一直使用class I pulled from CodeProject called CBitmapEx

该类管理数据缓冲区,并具有转换位图图像的有用功能。它被设计为使用32位图像,但我稍微修改了它,因为我将描述使用24位图像。

仅在特定情况下,当CBitmapEx实例的析构函数尝试释放它在创建时设置了分辨率时分配的内存时,我收到堆损坏错误。

我怀疑问题的根源在于一个方法,其中包含一些内联汇编,它将对另一个CBitmapEx的内容进行缩放绘制。

导致错误的标准是:

  • 位图的尺寸小于或等于416x416。 (测试过 仅限正方形尺寸,417x417及以上都很好)
  • 我在位图上执行了另一个CBitmapEx的缩放绘制 不同大小的实例,即使是任一方向上的一个像素。 当两者的尺寸相同时,腐败永远不会发生。

我在Direct2D窗口中显示目标位图,并且没有可视指示缩放绘制以任何方式失败。

CodeProject类适用于32位位图,但我使用的是24位,因此我必须在'drawScaled'方法的程序集中修改两行,结果是视觉上正确复制的图像。

在列表中有两行:

        add edi, 3
        add ebx, 3

我从原来改变了这些:

        add edi, 4
        add ebx, 4

此更改导致该方法在处理24位图像时正常工作。我的怀疑是,程序集中可能还有其他东西仍然是32位并且是问题的根源。任何人都可以在代码中看到这样的东西吗?

void CBitmapEx::drawScaled(long dstX,
                 long dstY,
                 long dstWidth,
                 long dstHeight,
                 CBitmapEx& bitmapEx,
                 long srcX,
                 long srcY,
                 long srcWidth,
                 long srcHeight){
// Check for valid bitmap
if (isValid() && bitmapEx.isValid())
{
    // Calculate destination params
    long _dstStartX = max(0, min(_bih.biWidth-1, dstX));
    if (srcX < 0)
        _dstStartX = max(0, min(_bih.biWidth-1, dstX-srcX));
    long _dstStartY = max(0, min(_bih.biHeight-1, dstY));
    if (srcY < 0)
        _dstStartY = max(0, min(_bih.biHeight-1, dstY-srcY));
    long _dstEndX = max(0, min(dstX+dstWidth, _bih.biWidth-1));
    long _dstEndY = max(0, min(dstY+dstHeight, _bih.biHeight-1));
    long _dstWidth = _dstEndX - _dstStartX + 1;
    long _dstHeight = _dstEndY - _dstStartY + 1;

    // Calculate source params
    long _srcStartX = max(0, min(bitmapEx.getWidth()-1, srcX));
    if (dstX < 0)
        _srcStartX = max(0, min(bitmapEx.getWidth()-1, srcX-dstX));
    long _srcStartY = max(0, min(bitmapEx.getHeight()-1, srcY));
    if (dstY < 0)
        _srcStartY = max(0, min(bitmapEx.getHeight()-1, srcY-dstY));
    long _srcEndX = max(0, min(srcX+srcWidth, bitmapEx.getWidth()-1));
    long _srcEndY = max(0, min(srcY+srcHeight, bitmapEx.getHeight()-1));
    long _srcWidth = _srcEndX - _srcStartX + 1;
    long _srcHeight = _srcEndY - _srcStartY + 1;

    // Check drawing region
    if ((_dstWidth == 0) || (_dstHeight == 0) || (_srcWidth == 0) || (_srcHeight == 0))
        return;

    // Calculate scaling params
    long _height = bitmapEx.getHeight();
    long _pitch = bitmapEx.getPitch();
    long _bpp = bitmapEx.getBpp() >> 3;
    float dx = (float)_srcWidth / (float)_dstWidth;
    float dy = (float)_srcHeight / (float)_dstHeight;
    fixed f_dx = ftofx(dx);
    fixed f_dy = ftofx(dy);

    // Draw bitmap
    DWORD dwDstHorizontalStartOffset = _dstStartX * _iBpp;
    DWORD dwDstVerticalOffset = (_bih.biHeight-_dstStartY-1) * _iPitch;
    LPDWORD lpDstData = (LPDWORD)_lpData;
    LPDWORD lpSrcData = (LPDWORD)bitmapEx.getData();
    DWORD dwDstPitch = _iPitch;

    __asm {
        mov edi, lpDstData
        add edi, dwDstVerticalOffset
        add edi, dwDstHorizontalStartOffset
        xor edx, edx
outer_loop: 
        xor ecx, ecx
        xor ebx, ebx
inner_loop: 
        push ebx
        push edx
        mov ebx, _height
        sub ebx, _srcStartY
        mov eax, edx
        shl eax, 8
        mul f_dy
        shr eax, 16
        sub ebx, eax
        dec ebx
        mov eax, ebx
        mul _pitch
        push eax
        mov ebx, _srcStartX
        mov eax, ecx
        shl eax, 8
        mul f_dx
        shr eax, 16
        add eax, ebx
        mul _bpp
        pop ebx
        add eax, ebx
        mov esi, lpSrcData
        add esi, eax
        mov eax, [esi]
        mov [edi], eax
        pop edx
        pop ebx
        add edi, 3
        add ebx, 3
        inc ecx
        cmp ecx, _dstWidth
        jl inner_loop
        sub edi, ebx
        sub edi, dwDstPitch
        inc edx
        cmp edx, _dstHeight
        jl outer_loop
    }
}
}

0 个答案:

没有答案