C++Builder 11引入TIdHTTP触发memcpy调用歧义错误求规避方案
问题概述
用C++Builder 11开发64位VCL Windows应用,程序依赖第三方组件FlexCompress,它自动生成的头文件FXCZLib.hpp里定义了一个自定义memcpy函数。引入Indy组件TIdHTTP(版本10.6.2.0)后,出现编译错误:
[bcc64 Error] ws2tcpip.h(817): call to 'memcpy' is ambiguous
编译器无法区分该调用mem.h中的标准库版本,还是FXCZLib.hpp中的自定义版本,且无法安全修改这些第三方/系统头文件,以下是几个可行的规避方案。
相关代码片段
ws2tcpip.h中的出错位置代码
if (Error == 0) { if (*SourceCount > 0) { CopyMemory(SourceList, Filter->imsf_slist, *SourceCount * sizeof(*SourceList)); *SourceCount = Filter->imsf_numsrc; } *FilterMode = Filter->imsf_fmode; }
FXCZLib.hpp里的memcpy定义
extern DELPHI_PACKAGE void __cdecl memcpy(void * dest, void * Source, int Count);
mem.h里的标准memcpy定义
void _FAR * _RTLENTRY _EXPFUNC memcpy(void _FAR *__dest, const void _FAR *__src, _SIZE_T __n);
可行的规避方案
1. 调整头文件引入顺序
将Indy或系统相关头文件放在FXCZLib.hpp之前引入,让编译器优先识别标准库的memcpy:
// 先引入Indy头文件 #include <IdHTTP.hpp> // 再引入FlexCompress的头文件 #include "FXCZLib.hpp"
原理:C++编译器按顺序处理头文件,先加载的函数定义会被优先识别,编译ws2tcpip.h时只会匹配到标准库的memcpy,避免歧义。
2. 给FlexCompress的memcpy套命名空间
无需修改原FXCZLib.hpp,自行编写中间头文件进行包装:
- 新建
WrappedFXCZLib.hpp,内容如下:
namespace FlexCompress { #include "FXCZLib.hpp" }
- 在代码中用这个中间头文件替代原
FXCZLib.hpp,调用FlexCompress的memcpy时加上命名空间:
#include <IdHTTP.hpp> #include "WrappedFXCZLib.hpp" // 调用FlexCompress的memcpy FlexCompress::memcpy(dest, src, count);
原理:将FlexCompress的所有符号(包括自定义memcpy)限定在自定义命名空间内,标准库的memcpy保持全局可见,编译器处理ws2tcpip.h时只会识别标准版本。
3. 用预编译宏重命名FlexCompress的memcpy
在引入Indy头文件之前,临时重命名FlexCompress的memcpy:
// 定义宏,将FXCZLib里的memcpy替换为别名 #define memcpy __flex_memcpy #include "FXCZLib.hpp" // 取消宏定义,恢复标准memcpy #undef memcpy // 再引入Indy头文件 #include <IdHTTP.hpp>
如果需要调用FlexCompress的memcpy,使用宏定义的别名即可:
__flex_memcpy(dest, src, count);
原理:通过宏替换避免两个memcpy重名,编译Indy相关代码时只会匹配到标准库版本。
4. 强制指定标准库memcpy(针对特定报错位置)
若错误仅出现在ws2tcpip.h中,在引入该头文件前强制指定使用标准库版本:
// 强制编译器使用标准库的memcpy #define memcpy std::memcpy #include <ws2tcpip.h> #undef memcpy // 再引入其他头文件 #include <IdHTTP.hpp> #include "FXCZLib.hpp"
注意:需确保ws2tcpip.h不依赖FlexCompress的memcpy实现,否则可能引发其他问题。
内容的提问来源于stack exchange,提问作者WorldTalk

