使用memcpy时出现访问违例

xianshui 2009-07-07 04:56:48
本来是想要做中值滤波的

看到有人对8位位图做了一个中值滤波的程序,于是希望进行适当修改让其能够应付真彩色位图。。

在还进入中值滤波具体数据替换阶段前,该程序做了这样一件事情,首先根据位图的位数来计算位图每一行的像素应该占据的字节数,因为是16位,所以没有调色板,每一个像素应该是用RGB值直接表示,而且每一个分量应该要用到一个字节,那么也就是说每一行的每一个像素都要占3个字节,而由于BMP的像素数据区的存储方式规定:图像每一行所有的像素所占用的字节数应该是4的整数倍,于是我对原程序中每一行所占用的字节数的公式做出这样的修正:
lLineBytes = lWidth * 3 + (4 - (lWidth * 3) % 4) % 4; 其中lWidth为图像宽度。程序原来是“(((lWidth * 8) + 31) / 32 * 4)”

接着,该程序用hNewDIBBits = LocalAlloc(LHND, lLineBytes * lHeight)另外开辟了一段空间,为了保存滤波之后的图像,而不动源图像。接着用lpNewDIBBits = (char * )LocalLock(hNewDIBBits)拿到新空间的首位指针。。

下一步,它memcpy(lpNewDIBBits, lpDIBBits, lLineBytes * lHeight)把lpDIBBits(这个是指向源图像的指针)指向的图图内容copy到新开辟的空间里面去

但是,就是因为我改了上面那个1LineBytes的算式,于是这里就在我运行程序的时候给出了“访问违例”的提示。。

程序停在了下面给出的asm的倒数第二行

--------------------------------------------
CopyUp:
test edi,11b ;U - destination dword aligned?
jnz short CopyLeadUp ;V - if we are not dword aligned already, align

shr ecx,2 ;U - shift down to dword count
and edx,11b ;V - trailing byte count

cmp ecx,8 ;U - test if small enough for unwind copy
jb short CopyUnwindUp ;V - if so, then jump

-> rep movsd ;N - move all of our dwords //程序停在了这一行前

jmp dword ptr TrailUpVec[edx*4] ;N - process trailing bytes

--------------------------------------------

请问,可能有虾米原因不?
...全文
149 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
xianshui 2009-07-08
  • 打赏
  • 举报
回复
To 沙发的 “arong1234 ”
-------------------------------------------------------------------
很显然line*height是肯定不够得
1。每个pixel得颜色可能不止一个字节(例如4字节RGB需要得空间就是4倍)
2. 每行得空间数大于他得列数,这是为什么你要有那么复杂得表达式得原因

确保目标和源长度计算用同一个公式,你用不同公式又不确保他们一样当然有问题了
------------------------------------------------------------------

我不太理解你的这句话的意思。。正是因为不是用调色板显示,所以16位在这里是用RGB三色值来存储的。。

“目标和源长度计算用同一公式”。。在我的理解里面,源图像的数据控件长度就是 一行的像素RGB值需要的字节数(4的倍数)*图像的高度 ,而分配的空间也就是按照这个想法分配的,如果有错,请问,源长度应该咋算呢?
xianshui 2009-07-08
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 zhangyan_wt 的回复:]
lLineBytes 算法没有错,虽然稍微罗嗦了一些,可以改进一下:
lLineBytes = (lWidth * 3 + 3) / 4 * 4;

死机的问题我觉得目的内存是没错的,关键在于源内存是否有这么大,应该根据实际图像的bitcount决定要怎么开辟内存,保证源内存空间,目的内存的空间是一样大的,而且和复制的内存数相同。
[/Quote]

因为是16位,没有调色板,所以我才认为数据空间应该是1LineBytes*lHeight(图像高度)这么大。。请问,这样认为是不是有错?
xianshui 2009-07-08
  • 打赏
  • 举报
回复
好了,我大概知道原因了。。具体对不对没有试验,只是24位就成功了。。

16位位图一个像素不是我所想的RGB分量分别占用1个字节,由于16位有两种编码格式565和555,常用的555是这样的。。

16色:
R-->5位
G-->5位
B-->5位
还有一位保留

也就是说,其实合起来才2个字节,而不是24位位图,24位的一个像素才是真正的RGB分别占用1个字节,当我把一个24位位图放进自己的程序当中运行时,没有再跑出那可爱的访问违例了。。

结贴了,呵呵。
zhangyan_wt 2009-07-07
  • 打赏
  • 举报
回复
lLineBytes 算法没有错,虽然稍微罗嗦了一些,可以改进一下:
lLineBytes = (lWidth * 3 + 3) / 4 * 4;

死机的问题我觉得目的内存是没错的,关键在于源内存是否有这么大,应该根据实际图像的bitcount决定要怎么开辟内存,保证源内存空间,目的内存的空间是一样大的,而且和复制的内存数相同。
ChamPagneZ 2009-07-07
  • 打赏
  • 举报
回复

//拿去试一试吧,
hNewDIBBits = LocalAlloc(LHND, lLineBytes * lHeight + 1);
lpNewDIBBits = (char * )LocalLock(hNewDIBBits);
ZeroMemory(lpNewDIBBits ,lLineBytes * lHeight + 1);
arong1234 2009-07-07
  • 打赏
  • 举报
回复
你为什么源长度用一个公式,分配空间用另外一个?
[Quote=引用 2 楼 xianshui 的回复:]
虽然我晓得memcpy的src和dest所指内存区域不能重叠,另外拷贝的内容不能越界,但是想想,这问题估计就出在我那个 图像像素字节数 算法上,可是我还真是想不通了捏,请给点指点,谢谢
[/Quote]
arong1234 2009-07-07
  • 打赏
  • 举报
回复
很显然line*height是肯定不够得
1。每个pixel得颜色可能不止一个字节(例如4字节RGB需要得空间就是4倍)
2. 每行得空间数大于他得列数,这是为什么你要有那么复杂得表达式得原因

确保目标和源长度计算用同一个公式,你用不同公式又不确保他们一样当然有问题了
xianshui 2009-07-07
  • 打赏
  • 举报
回复
虽然我晓得memcpy的src和dest所指内存区域不能重叠,另外拷贝的内容不能越界,但是想想,这问题估计就出在我那个 图像像素字节数 算法上,可是我还真是想不通了捏,请给点指点,谢谢
arong1234 2009-07-07
  • 打赏
  • 举报
回复
一般都是目的缓冲区空间不足, 你超过了分配给你得空间

16,551

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Creator Browser
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧