我有一个后台线程加载图像(从磁盘或服务器),目标是最终将它们传递给主线程进行绘制.当第二个线程使用VCL TGIFImage类加载GIF图像时,每次在线程中执行以下行时,此程序有时会泄漏几个句柄:
m_poBitmap32->Assign(poGIFImage);
Run Code Online (Sandbox Code Playgroud)
也就是说,刚刚打开的GIF图像被分配给线程拥有的位图.这些都不与任何其他线程共享,即完全本地化到线程.它与时序有关,因此每次执行该行时都不会发生,但是当它确实发生时,它只发生在该行上.每个泄漏都是一个DC,一个调色板和一个位图.(我使用GDIView,它提供比Process Explorer更详细的GDI信息.) m_poBitmap32这是一个Graphics32 TBitmap32对象,但我使用普通的VCL专用类重现了这一点,即使用Graphics::TBitmap::Assign.
最终我得到一个EOutOfResources异常,可能表明桌面堆已满:
:7671b9bc KERNELBASE.RaiseException + 0x58
:40837f2f ; C:\Windows\SysWOW64\vclimg140.bpl
:40837f68 ; C:\Windows\SysWOW64\vclimg140.bpl
:4084459f ; C:\Windows\SysWOW64\vclimg140.bpl
:4084441a vclimg140.@Gifimg@TGIFFrame@Draw$qqrp16Graphics@TCanvasrx11Types@TRectoo + 0x4a
:408495e2 ; C:\Windows\SysWOW64\vclimg140.bpl
:50065465 rtl140.@Classes@TPersistent@Assign$qqrp19Classes@TPersistent + 0x9
:00401C0E TLoadingThread::Execute(this=:00A44970)
Run Code Online (Sandbox Code Playgroud)
如何TGIFImage在后台线程中解决此问题并安全使用?
其次,我会遇到PNG,JPEG或BMP类的同样问题吗?我还没有到目前为止,但鉴于它是一个线程/时间问题并不意味着如果他们使用相似的代码我就不会TGIFImage.
我正在使用C++ Builder 2010(RAD Studio的一部分.)
一些研究表明,我不是唯一遇到这种情况的人.引用一个帖子,
Help(2007)说:在使用Lock保护画布的多线程应用程序中,所有使用画布的调用都必须通过调用Lock来保护.在使用之前没有锁定画布的任何线程都会引入潜在的错误.
[...]
但是这个陈述是绝对错误的:即使其他线程没有触摸它,你也必须在辅助线程中锁定画布.否则,画布的GDI句柄可以在主线程中随时释放(异步).
另一个回复表明类似的东西,它可能与graphics.pas中的GDI对象缓存有关.
这很可怕:在一个线程中完全创建和使用的对象可以在主线程中异步释放一些资源.不幸的是,我不知道如何应用Lock建议TGIFImage. TGIFImage没有Canvas,虽然它确实有Bitmap一个画布.锁定无效.我怀疑这个问题实际上是TGIFFrame一个内部课程.我也不知道是否或如何锁定任何TBitmap32资源.我确实尝试将TMemoryBackend位图分配给位图,这避免了使用GDI,但它没有任何效果.
我在软件中遇到了一个奇怪的崩溃,我在调试它时遇到了很多麻烦,因此我正在寻求如何解决它的建议.
崩溃是读取NULL指针的访问冲突:
$ 00CF0041的第一次机会异常.异常类$ C0000005,消息'访问冲突位于0x00cf0041:读取地址0x00000000'.
它只发生'有时' - 我还没有设法找出任何押韵或理由,但是,当时 - 并且只在主线程中.当它发生时,调用堆栈包含一个不正确的条目:

对于主线程,它应该显示一个充满其他项目的大堆栈.
此时,所有其他线程都处于非活动状态(主要是坐在WaitForSingleObject或类似的功能.)我只看到这个崩溃发生在主线程中.它始终具有一个条目的相同调用堆栈,在同一地址的相同方法中.此方法可能相关也可能不相关 - 我们在应用程序中使用VCL.不过,我的赌注是,某些东西(可能是很久以前)正在破坏堆栈,而崩溃的地址实际上是随机的.请注意,它在几个版本中的地址相同 - 但它可能不是真正随机的.
这是我尝试过的:
我的问题:
1.如何找到导致崩溃的代码?我怎么做相当于走回堆栈?
2.对于如何追踪此次崩溃的原因,您有什么一般性的建议?
我正在使用Embarcadero RAD Studio 2010(该项目主要包含C++ Builder代码和少量Delphi.)
编辑:我想我应该添加实际导致这个的东西.有一个线程调用ReadDirectoryChangesW然后,使用GetOverlappedResult,等待事件继续并对更改执行某些操作.事件也发出信号,以便在设置状态标志后终止线程.问题是当线程退出时它从未调用过CancelIO.因此,Windows仍在跟踪更改,并且可能仍然在目录更改时写入缓冲区,即使缓冲区,重叠的结构和事件不再存在(也没有创建它们的线程上下文.)CancelIO调用时,没有更多的崩溃.
我需要绘制一个正方形图像,映射或转换为未知的编译时四边形多边形.我怎样才能做到这一点?
具体问题是渲染具有非矩形地图投影的地图图块.假设我有以下磁贴:

我知道需要有四个角点:

鉴于此,我想得到以下输出:

方形瓷砖可能是:
我认为第二项意味着这需要非仿射变换.
随机附加说明
四面?完全正确的情况是合理的,瓷砖应该映射到具有四个以上点的多边形,但是对于我们的目的和绘制的尺度,方形 - >其他四角多边形变换应该足够了.
为什么只有GDI? 到目前为止,所有渲染都是使用GDI完成的,我希望快速保持代码(a),并且(b)需要尽可能少的额外库.我知道有一些对GDI转换的支持,并且今天一直在试验它们,但即使在试验它们之后,我也不确定它们是否足够灵活用于此目的.如果他们是,我还没有设法弄清楚,所以我真的很感激一些示例代码.
GDI +也可以,因为我们在其他地方使用它,但我知道它可能很慢,速度在这里很重要.
另一种选择是Delphi - / C++ Builder特有的; 这个程序主要是用C++编写的,使用的是VCL,所讨论的图形目前被绘制成TCanvas,混合使用TCanvas方法和原始WinAPI/GDI调用.
叠加图像:最后一点需要注意的是,图块中的一种颜色可能是用于颜色键的透明度:也就是说,上面图块中的所有白色(说)方块在绘制在下面的任何内容时应该是透明的.目前,使用TransparentBlt将切片绘制到方形或轴对齐的矩形目标.
对于让这个问题比"我应该使用什么算法?"更复杂的所有额外警告我感到抱歉.但我也很乐意接受只有算法信息的答案.
我维护一个可以通过COM自动化的程序.通常客户使用VBS来编写脚本,但我们有几个客户使用Matlab的ActiveX支持,并且在使用NULL参数调用COM对象方法时遇到问题.
他们已经问过他们是如何在Matlab中做到这一点的 - 而且我已经在Mathworks的COM/ActiveX文档中搜索了一天左右,现在无法弄明白.
他们的示例代码可能如下所示:
function do_something()
OurAppInstance = actxserver('Foo.Application');
OurAppInstance.Method('Hello', NULL)
end
Run Code Online (Sandbox Code Playgroud)
这里NULL就是另一种语言,我们会写NULL或nil或Nothing或,当然,传中的对象.问题是这是可选的(并且这些在大多数情况下都是作为可选参数实现的,但并非所有情况都是如此) - 这些方法经常会出现NULL.
他们告诉我,他们已经尝试过[](从我的阅读似乎是最有可能的),以及'',Nothing,'Nothing',None,Null,和0.我不知道有多少甚至是有效的Matlab关键字 - 在这种情况下肯定都不起作用.
有人可以帮忙吗?什么是Matlab的空指针/对象的语法用作COM方法参数?
更新:感谢您到目前为止的所有回复!不幸的是,没有一个答案似乎有效,甚至没有libpointer.在所有情况下错误都是相同的:
Error: Type mismatch, argument 2
COM类型库中的此参数在RIDL中描述为:
HRESULT _stdcall OurMethod([in] BSTR strParamOne, [in, optional] OurCoClass* oParamTwo, [out, retval] VARIANT_BOOL* bResult);
Run Code Online (Sandbox Code Playgroud)
有问题的coclass实现了从IDispatch下降的单个接口.
我正在使用Julian Bucknall在其着名的书" The Tomes Of Delphi"中编写的红黑树实现.源代码可以在这里下载,我在Delphi 2010中使用代码,并进行修改TdBasics.pas,让它在Delphi的现代版本中进行编译(主要是对大部分内容进行注释 - 树只需要一些定义)码.)
这是着名作家在一本经常推荐的书中的一个众所周知的实现.我觉得我应该坚持使用它.但我正在遇到使用Delete()和崩溃的崩溃Promote().回过头来用DUnit编写单元测试,这些问题很容易重现.一些示例代码是(来自我的DUnit测试的片段):
// Tests that require an initialised tree start with one with seven items
const
NumInitialItems : Integer = 7;
...
// Data is an int, not a pointer
function Compare(aData1, aData2: Pointer): Integer;
begin
if NativeInt(aData1) < NativeInt(aData2) then Exit(-1);
if NativeInt(aData1) > NativeInt(aData2) then Exit(1);
Exit(0);
end;
// Add seven items (0..6) to the tree. Node.Data is a pointer field, …Run Code Online (Sandbox Code Playgroud) 我在窗口上,在启用了DWM组合的系统上使用双缓冲GDI绘制动画,并在屏幕上看到清晰可见的撕裂.有办法防止这种情况吗?
动画采用相同的图像,并在屏幕上从右向左移动; 像素跨越由当前时间和动画开始时的时间和时间,以端之间的差确定的数量,以便获得完整的一小部分被施加到整个窗口宽度,使用timeGetTime具有1毫秒的分辨率.动画绘制循环而不处理应用程序消息; 它调用Repaint内部无效的(VCL库)方法,然后调用UpdateWindow有问题的窗口,直接调用消息过程WM_PAINT.绘图处理程序的VCL实现使用BeginBufferedPaint.绘画本身是双重缓冲的.
这样做的目的是使帧速率尽可能高,以在屏幕上获得平滑的动画效果.(该图使用双缓冲来消除闪烁并确保整个图像或帧在任何时间都在屏幕上.它通过调用消息过程直接无效和更新,而不进行其他消息处理.绘画使用现代技术实现(例如,BeginAfferedPaint)用于Aero组合.)在此之内,绘画是在几个BitBlt调用中完成的(一个用于动画的左侧,即在屏幕外移动,一个用于动画的右侧,即在屏幕上移动的内容). )
观看动画时,会有明显的撕裂现象.这种情况发生在具有不同图形卡的多个系统上的Windows Vista,7和8.1上.
我处理这个问题的方法是降低绘图速度,或者在再次绘制之前尝试等待VSync.这可能是错误的方法,所以这个问题的答案可能是"完全做其他事情:X".如果是这样,很棒:)
(我真正喜欢的是一种让DWM为这个特定窗口组成/仅使用完全绘制的帧的方法.)
我尝试了以下方法,其中没有一个删除所有可见的撕裂.因此问题是,在使用DWM组合时是否可以避免撕裂,如果是这样的话?
获取显示器刷新率GetDeviceCaps(Application.MainForm.Handle, VREFRESH); 睡眠1 /刷新率毫秒.尽可能快地改善绘画,但可能是一厢情愿的想法.感觉上动画率稍微不那么平滑.(调整:正常Sleep和高分辨率旋转等待使用timeGetTime.)
使用DwmSetPresentParameters尝试更新限制到该代码绘制相同的速度.(变化:大量缓冲区(cBuffer = 8)(无可见效果);使用上面的代码指定监视器刷新率/ 1和睡眠的源速率(与尝试休眠方法相同);指定每帧的刷新次数1,10等(无可见效果);更改源帧覆盖范围(无可见效果)
使用DwmGetCompositionTimingInfo在多种方式:
cFramesPending> 0时,旋转;cFrame(框架组合)并旋转,而这个数字不会改变;cFrameDisplayed并旋转,而这不会改变;qpcVBlank + qpcRefreshPeriod,然后在QueryPerformanceCounter返回时间小于此时旋转所有这些方法也通过绘画,然后在再次绘画之前旋转/睡觉而变化; 或者相反:睡觉然后画画.
似乎没有任何可见效果,并且有什么效果很难获得资格,可能只是帧率较低的结果.没有防止撕裂,即没有人使DWM用窗口DC内容的"整体"副本组成窗口.
建议赞赏:)
关于lock_guard存在的原因,我很困惑.是吗:
unique_lock?unique_lock?我们的应用程序的源代码是数十万行,数千个文件,并且在非常古老的地方 - 该应用程序最初是在1995年或1996年编写的.在过去的几年里,我的团队已经大大提高了源代码的质量,但是一个问题仍然是特别困扰我:许多类在其头文件中完全定义了许多方法.
在某些情况下,我对在头文件中内联声明的方法没有任何问题 - 一个struct的构造函数,一个简单的方法,其中内联可以使它更快(我们有一些像这样的数学函数),等等.但内联方法的自由使用没有明显原因是:
最后一个原因现在可能会给我们带来问题,这是通过代码库并将大多数定义移动到源文件的一个很好的理由.
我们的代码库非常庞大. 是否有可以为我们(大部分)做这个的自动化工具?
笔记:
微软最近宣布了Fluent Design中的玻璃状材料Acrylic.它仅作为XAML/UWP呈现,但看起来非常类似于玻璃,除了它可以任意着色并且可以应用于应用程序中的天桥控件以及应用程序的独立窗口.
'配方'使它看起来好像是在XAML中实现的,而不是暴露在更广泛的系统中.
一个相关的SO问题证实了这一点(它缺乏具体的技术答案,但暗示丙烯酸不能通过WinAPI以玻璃的方式获得.)
如何在一个普通的Win32应用程序中模仿这个? 用玻璃和混合?(哪些API,以及Win7中不存在的Win10 Fall Update的玻璃API有哪些?)如果应用程序是使用Win32创建的,但使用DirectX表面进行渲染,是否会打开更多可能性?
这是前一个问题的一个子集.
作为练习,我正在编写一个内存管理器 - 即实现malloc,realloc和free(或new和delete)的代码.我的语言Delphi 的RTL允许轻松替换RTL的内存管理器.对于那些使用C++的人来说,这类似于,但是低于覆盖新的和删除(它挂钩到RTL本身而不是语言功能.)
我正在寻找有关高质量方法的资源,其他人已经解决了同样的问题,并试图找出其他主要编译器供应商使用的算法.虽然Delphi有很好的文档记录,但我找不到有关MS VC++,.Net或Objective C所使用的实现的任何信息.这些供应商似乎(?)不允许他们的RTL像Delphi那样被挂钩.所有文档似乎都是更高级别的,例如NSAutoReleasePool选择一个随机的例子 - 对于这个问题来说太高级了.
主要供应商(Microsoft VC++和.Net以及Apple Objective C)在其运行时库中使用哪些内存管理算法?
一个很好的答案的例子是描述内存管理器实现的文档,例如这个,或者是发布论文的链接.一个有用的答案的例子是算法,'VC++运行时使用Hoard分配器 '.
delphi ×5
c++builder ×3
gdi ×3
algorithm ×2
c++ ×2
dwm ×2
winapi ×2
windows ×2
automation ×1
c++11 ×1
callstack ×1
com ×1
crash ×1
gdi+ ×1
graphics ×1
inline ×1
matlab ×1
memory-leaks ×1
msvcrt ×1
mutex ×1
null ×1
objective-c ×1
parameters ×1
refactoring ×1
transform ×1
tree ×1