热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Bitmap.LockBits是否将位图“固定”到内存中?-DoesBitmap.LockBits“pin”abitmapintomemory?

Imusinglockedbitmapsalotrecently,andIkeepgettingattemptedtoaccessinvalidmemoryerr

I'm using locked bitmaps a lot recently, and I keep getting "attempted to access invalid memory" errors. This is mostly because the bitmap has been moved in memory. Some people using GCHandle.Alloc() to allocate memory in the CLR and pin it. Does Bitmap.LockBits() do the same? I don't understand the difference between "locking" memory and "pinning" memory. Can you also explain the terminology and the differences if any?

我最近使用锁定的位图,并且一直“试图访问无效内存”错误。这主要是因为位图已在内存中移动。有些人使用GCHandle.Alloc()在CLR中分配内存并固定它。 Bitmap.LockBits()也这样做吗?我不明白“锁定”内存和“固定”内存之间的区别。你能解释术语和差异吗?

2 个解决方案

#1


8  

GCHandle.Alloc is a more generic method, that allows you to allocate a handle to any managed object and pin it in memory (or not). Pinning memory prevents GC from moving it around, which is especially useful when you have to pass some data, for example an array, to a unmanaged code.

GCHandle.Alloc是一种更通用的方法,允许您为任何托管对象分配句柄并将其固定在内存中(或不固定)。固定内存会阻止GC移动它,这在您必须将某些数据(例如数组)传递给非托管代码时尤其有用。

GCHandle.Alloc will not help you access bitmap's data in any way, because pinning this object will just prevent the managed object from moving around (the Bitmap object) (and being garbage collected).

GCHandle.Alloc不会以任何方式帮助您访问位图的数据,因为固定此对象只会阻止托管对象移动(Bitmap对象)(并进行垃圾回收)。

Bitmap however is a wrapper around native GDI+'s BITMAP structure. It doesn't keep data in any managed array that you would have to pin, it just managed a native handle to GDI+ bitmap object. Because of that Bitmap.LockBits is a way of telling this bitmap that you are interested in accessing it's memory, and it's just a wrapper around GdipBitmapLockBits function. So your need of calling it has more to do with the fact that you are working with GDI+ bitmaps than with the fact, that you're working in managed environment with GC.

然而,Bitmap是本机GDI +的BITMAP结构的包装器。它不会将数据保存在您必须固定的任何托管数组中,它只是管理了GDI +位图对象的本机句柄。因为Bitmap.LockBits是一种告诉这个位图的方式,你有兴趣访问它的内存,它只是GdipBitmapLockBits函数的包装器。因此,您需要调用它更多地与您使用GDI +位图这一事实有关,而不是与您在使用GC的托管环境中工作的事实有关。

Once you have used LockBits you should be able to access it's memory using pointers through BitmapData.Scan0 - it's an address of first byte of data. You should not have problems as long, as you do not access memory behind BitmapData.Scan0 + Height * Stride.

一旦你使用了LockBits,你应该能够通过BitmapData.Scan0使用指针访问它的内存 - 它是数据第一个字节的地址。你应该没有问题,因为你没有访问BitmapData.Scan0 + Height * Stride后面的内存。

And rememberto UnlockBits when you are done.

当你完成时,记得UnlockBits。

#2


1  

In your case an attempted to access invalid memory error is most probably caused by invalid memory allocation which you are doing in the unsafe part of code, e.g allocated array is smaller than number of pixels you are trying to put in that.

在您的情况下,尝试访问无效内存错误很可能是由于您在代码的不安全部分进行的无效内存分配造成的,例如,分配的数组小于您尝试放入的像素数。

There is also no need to think about pinning the objects unless your image data is less than 85000 Bytes as only objects less than 85K will be moved in memory.

除非您的图像数据小于85000字节,否则也无需考虑固定对象,因为只有小于85K的对象将在内存中移动。

Another story would be if you pass the object to unmanaged code, for example in the c++ library for faster processing. In this case your exception is very possible if the passed image gets out of scope and will be garbage collected. In this case you can use GCHandle.Alloc(imageArray,GCHandleType.Pinned); and than call Free if you do not need it any longer.

另一个故事是,如果您将对象传递给非托管代码,例如在c ++库中以便更快地处理。在这种情况下,如果传递的图像超出范围并且将被垃圾收集,则很可能发生异常。在这种情况下,您可以使用GCHandle.Alloc(imageArray,GCHandleType.Pinned);如果您不再需要它,请致电免费。


推荐阅读
  • JDK源码学习之HashTable(附带面试题)的学习笔记
    本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • LeetCode笔记:剑指Offer 41. 数据流中的中位数(Java、堆、优先队列、知识点)
    本文介绍了LeetCode剑指Offer 41题的解题思路和代码实现,主要涉及了Java中的优先队列和堆排序的知识点。优先队列是Queue接口的实现,可以对其中的元素进行排序,采用小顶堆的方式进行排序。本文还介绍了Java中queue的offer、poll、add、remove、element、peek等方法的区别和用法。 ... [详细]
  • Whatsthedifferencebetweento_aandto_ary?to_a和to_ary有什么区别? ... [详细]
  • 本文讨论了微软的STL容器类是否线程安全。根据MSDN的回答,STL容器类包括vector、deque、list、queue、stack、priority_queue、valarray、map、hash_map、multimap、hash_multimap、set、hash_set、multiset、hash_multiset、basic_string和bitset。对于单个对象来说,多个线程同时读取是安全的。但如果一个线程正在写入一个对象,那么所有的读写操作都需要进行同步。 ... [详细]
  • Iamtryingtocreateanarrayofstructinstanceslikethis:我试图创建一个这样的struct实例数组:letinstallers: ... [详细]
  • 深入理解Java虚拟机的并发编程与性能优化
    本文主要介绍了Java内存模型与线程的相关概念,探讨了并发编程在服务端应用中的重要性。同时,介绍了Java语言和虚拟机提供的工具,帮助开发人员处理并发方面的问题,提高程序的并发能力和性能优化。文章指出,充分利用计算机处理器的能力和协调线程之间的并发操作是提高服务端程序性能的关键。 ... [详细]
  • 如何自行分析定位SAP BSP错误
    The“BSPtag”Imentionedintheblogtitlemeansforexamplethetagchtmlb:configCelleratorbelowwhichi ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • Android JSON基础,音视频开发进阶指南目录
    Array里面的对象数据是有序的,json字符串最外层是方括号的,方括号:[]解析jsonArray代码try{json字符串最外层是 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • CentOS 7部署KVM虚拟化环境之一架构介绍
    本文介绍了CentOS 7部署KVM虚拟化环境的架构,详细解释了虚拟化技术的概念和原理,包括全虚拟化和半虚拟化。同时介绍了虚拟机的概念和虚拟化软件的作用。 ... [详细]
  • Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOMEbinjava–option来启 ... [详细]
  • Jquery 跨域问题
    为什么80%的码农都做不了架构师?JQuery1.2后getJSON方法支持跨域读取json数据,原理是利用一个叫做jsonp的概念。当然 ... [详细]
author-avatar
Remember_Mi
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有