C代码编译出现warning C4273(不一致DLL链接)问题求助
解决MSVC编译C代码时的warning C4273(不一致DLL链接)问题
问题背景
x64编译环境下编译C代码,触发warning C4273(不一致DLL链接),查阅微软官方文档后未找到适配自身场景的解决办法。
代码细节
头文件与条件编译逻辑
shell.c开头先引入<stdio.h>,随后有一段条件编译代码:
#if defined(_WIN32) || defined(WIN32) # include <io.h> #define isatty(h) _isatty(h) #define access(f,m) _access((f),(m)) #undef popen #define popen _popen #undef pclose #define pclose _pclose #else /* Make sure isatty() has a prototype. */ extern int isatty(int); #endif
手动声明的popen/pclose
文件第78行,有一段针对popen/pclose的手动声明:
/* popen and pclose are not C89 functions and so are sometimes omitted from ** the <stdio.h> header */ FILE *popen(const char*,const char*); int pclose(FILE*);
警告信息
编译时触发的警告内容:
c:\builds\pathShortened\3rdparty\ProjectA\shell\src\shell.c(78): warning C4273: "_popen": Inkonsistente DLL-Bindung.
编译命令
使用的CL.exe编译指令:
C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Tools\MSVC\14.16.27023\bin\HostX86\x64\CL.exe /c /I..\StaticLib\src /I..\StaticLib\inc /I..\StaticLib\inc_priv /I"C:\builds\pathShortened\3rdparty\ProjectA\PathPartBuild\packages\openssl.v140.windesktop.msvcstl.dyn.rt-dyn.x64.1.0.2.1\build\native\include" /I"C:\builds\pathShortened\3rdparty\ProjectA\PathPartBuild\packages\zlib.v140.windesktop.msvcstl.dyn.rt-dyn.1.2.8.8\build\native\include" /Zi /nologo /W3 /WX- /diagnostics:classic /O2 /Oi /GL /D NDEBUG /D WIN32 /D _CONSOLE /D _CRT_SECURE_NO_WARNINGS /D _MBCS /Gm- /EHa /MD /Zp8 /GS- /Gy /Qpar /fp:precise /Zc:wchar_t /Zc:forScope /Zc:inline /Fo"Bin\Release\x64\.tmp\\" /Fd"Bin\Release\x64\.tmp\vc141.pdb" /Gd /TC /FC /errorReport:queue /wd4005 /wd4505 /wd4514 /wd4131 Src\shell.c
问题根源与解决办法
根源解析
这个警告的本质是手动声明的popen和系统DLL中_popen的链接属性不匹配:
- 代码里通过
#define popen _popen把popen映射成_popen,但手动写的FILE *popen(const char*,const char*);没有加上系统_popen自带的__declspec(dllimport)属性(用/MD编译时,系统头文件里的_popen会带这个属性)。 - 编译器识别到同一函数(实际是
_popen)有两种不同的链接声明,因此抛出不一致警告。
可行解决办法
办法1:删掉手动声明,用系统头文件提供的声明
- 直接注释或删除第78行开始的
popen/pclose手动声明。 - 如果Windows环境下
<stdio.h>默认不暴露popen/pclose,可以在引入<stdio.h>之前定义#define _CRT_NONSTDC_NO_DEPRECATE或#define _CRT_NONSTDC_NO_WARNINGS(根据MSVC版本调整),强制让头文件输出这些函数的声明。
办法2:给手动声明加上匹配的链接属性
如果必须保留手动声明,修改声明以对齐系统的属性:
#if defined(_WIN32) || defined(WIN32) __declspec(dllimport) FILE *popen(const char*, const char*); __declspec(dllimport) int pclose(FILE*); #else FILE *popen(const char*, const char*); int pclose(FILE*); #endif
办法3:调整手动声明的位置
把手动声明移到#define popen _popen之后,这样预处理器会把手动声明的popen替换成_popen,自动继承系统头文件里_popen的正确链接属性:
#if defined(_WIN32) || defined(WIN32) # include <io.h> #define isatty(h) _isatty(h) #define access(f,m) _access((f),(m)) #undef popen #define popen _popen #undef pclose #define pclose _pclose /* 把手动声明移到宏定义之后 */ FILE *popen(const char*,const char*); int pclose(FILE*); #else /* Make sure isatty() has a prototype. */ extern int isatty(int); FILE *popen(const char*,const char*); int pclose(FILE*); #endif
内容的提问来源于stack exchange,提问作者mnemonic
相关产品推荐
相关产品推荐

