加载DLL时出现‘Duplicates not allowed’错误的原因是什么?
Embarcadero升级后LoadLibrary加载DLL触发EListError异常的解决思路
问题场景
从RAD Studio 10.1升级到11.1后,C++主程序调用LoadLibrary加载目标DLL时失败,抛出异常:
First chance exception at $74F3CA42. Exception class EListError with message 'Duplicates not allowed'.
异常调用栈
:74f3ca42 KERNELBASE.RaiseException + 0x62 :55c2c179 CustomIPTransport280.@System@Generics@Collections@%TDictionary__2$5_GUIDp17System@TMetaClass%@Add$qqrrx5_GUIDxp17System@TMetaClass + 0x4d :555c923e IndyIPCommon280.@Ippeercommon@initialization$qqrv + 0x5e :322599e1 ; B:\Build\CC32280MT.DLL :32259f88 CC32280MT.__wstartupd + 0xc0 :07c96f5a ; System.Win.Stdvcl :7702dd42 ntdll.RtlActivateActivationContextUnsafeFast + 0xe2 :77031843 ; ntdll.dll :770319b1 ; ntdll.dll :77032255 ntdll.RtlIsCriticalSectionLockedByThread + 0xb5 :7702e272 ; ntdll.dll :7702deb6 ntdll.LdrLoadDll + 0xf6 :74f21bc6 ; C:\WINDOWS\SysWOW64\KERNELBASE.dll :74f3cca1 KERNELBASE.LoadLibraryW + 0x11 :00481026 TfrmTkTicketInquiry::actEmailExecute(this=:04639B90, Sender=:02B24A60) :50173bfa rtl280.@System@Classes@TBasicAction@Execute$qqrv + 0x12 :5650799b vcl280.@Vcl@Controls@TControl@Perform$qqruiuii + 0x27 :5650c6ad vcl280.@Vcl@Controls@TWinControl@IsControlMouseMsg$qqrr24Winapi@Messages@TWMMouse + 0xb5 :56595367 ; B:\Build\vcl280.bpl :5650c3f7 vcl280.@Vcl@Controls@TWinControl@MainWndProc$qqrr24Winapi@Messages@TMessage + 0x2f :50174a32 rtl280.@System@Classes@TDataModule@WriteHeight$qqrp22System@Classes@TWriter + 0x22 :75070f1b USER32.AddClipboardFormatListener + 0x4b :75067eca ; C:\WINDOWS\SysWOW64\USER32.dll :75065c3a ; C:\WINDOWS\SysWOW64\USER32.dll :75065a00 USER32.DispatchMessageW + 0x10 :5664d69c vcl280.@Vcl@Forms@TApplication@ProcessMessage$qqrr6tagMSG + 0xf8 :75437464 ; C:\WINDOWS\SysWOW64\SHELL32.DLL
已知背景:
- 主程序和DLL均为C++编写,已在RAD 11.1中重新创建cbproj文件,解决了多数升级问题
- 两者都集成了DevExpress C++组件
- 其他EXE可正常加载该DLL,仅当前EXE出现异常
核心原因
从调用栈可见,异常触发在CustomIPTransport280的TDictionary.Add方法,属于Indy组件(IndyIPCommon280)的初始化阶段。本质是主程序与DLL重复注册了同一个GUID对应的元类,导致Indy初始化时向字典添加重复键值对,触发"Duplicates not allowed"错误。
常见诱因:
- 主程序和DLL对Indy组件的链接方式不一致(一个静态链接、一个动态链接),导致初始化逻辑重复执行
- DevExpress组件自带的Indy版本与项目中使用的公共Indy版本冲突,引发重复注册
- 项目包依赖配置错误,重复加载了包含Indy注册逻辑的BPL包
解决步骤
- 统一Indy组件链接方式:确保主程序和DLL要么都动态链接到同一版本的Indy BPL包,要么都静态链接。检查项目选项的
Packages设置,确认Indy相关包(如IndyIPCommon280.bpl、CustomIPTransport280.bpl)版本一致,无重复引用。 - 排查DevExpress依赖冲突:更新DevExpress到适配RAD 11.1的最新版本,或在DevExpress配置中指定使用项目的Indy组件,避免私有版本冲突。
- 清理重复初始化代码:检查主程序和DLL的初始化部分,移除手动注册Indy组件的重复代码,确保注册逻辑仅在一方执行(通常由主程序或共享包统一处理)。
- 对齐项目配置:对比能正常加载DLL的其他EXE的项目配置,重点核对编译器选项(如
Runtime Packages、Linking)、依赖包列表及加载顺序,确保输出目录中组件库版本统一。 - 定位重复注册源:使用Indy调试版本,在
Ippeercommon单元的初始化代码处设断点,查看重复添加的GUID和元类,精准定位重复注册的模块。
内容的提问来源于stack exchange,提问作者MathewJoy
相关产品推荐
相关产品推荐

