为何TinyCC在32位模式下无法链接标准C运行时函数,64位模式却正常?
TinyCC 32位模式编译调用msvcrt.dll的程序时出现未定义符号错误
当使用TinyCC的32位模式(-m32)编译调用msvcrt.dll中CRT函数/符号的程序时,编译会失败。执行以下命令:
tcc.exe -std=c11 -Wall -Werror -Wl,-subsystem=console -m32 .\main.c
会得到错误:
tcc: error: undefined symbol '_iob', missing __declspec(dllimport)?
该问题仅在-m32模式下出现,切换到64位模式(-m64)时,使用以下命令可正常编译运行:
tcc.exe -std=c11 -Wall -Werror -Wl,-subsystem=console -m64 .\main.c
问题细节
_iob并非唯一未解析的符号,printf、freopen、freopen_s等几乎所有CRT函数都会出现链接失败的情况。
已尝试的解决方法
所有以下操作均无法解决问题,TCC仍报相同的未定义符号错误:
- 添加
-lmsvcrt编译参数,或在代码中使用#pragma comment(lib, "msvcrt") - 用
_declspec(dllimport)或__attribute__((dllimport))修饰符号 - 尝试
-static、-shared等编译选项 - 对
C:\Windows\SysWow64\msvcrt.dll(甚至更早版本如msvcrt40.dll)执行tcc -impdef命令生成导入库 - 修改
-I和-L路径指向C:/Windows/SysWow64
验证信息
已通过DUMPBIN.exe确认,32位和64位版本的msvcrt.dll均导出了_iob及相关CRT符号。
示例代码
// #pragma comment(lib, "msvcrt") // __attribute__((dllimport)) extern __declspec(dllimport) FILE _iob[]; #include <windows.h> // 定义_MSVCRT_会使MinGW的stdio.h使用_iob而非_imp___iob;前者才在msvcrt.dll中定义。 // 尽管32位和64位版本的该dll都导出了_iob,TinyCC仍无法在前者中找到它。 #define _MSVCRT_ #include <stdio.h> void main() { // AllocConsole()及kernel32.dll或user32.dll中的几乎所有函数,在-m32和-m64模式下都能正常工作; // 只有msvcrt.dll会给TinyCC带来问题。 AllocConsole(); // 任何CRT函数(如freopen、freopen_s、printf等)仅在-m32模式下无法正确链接;-m64模式正常。 // 即使修改-I和-L路径指向C:/Windows/SysWow64,或使用tcc.exe -impdef从其中生成.def文件, // TCC仍无法找到_iob及其他符号。使用#pragma comment(lib, "msvcrt")或-lmsvcrt也毫无帮助。 // 即使设法让TCC停止抱怨缺失符号,它也只会生成空白的IAT.printf或IAT.freopen,导致段错误。 freopen("CONOUT$", "w", stdout); printf("This only compiles (and prints) under TCC in 64-bit mode."); }
总结
-m32模式下的错误不受-std、-shared、-static、-lmsvcrt、-subsystem等编译选项影响,推测这可能是TinyCC 0.9.27(Win32和Win64版本)本身的bug。
内容的提问来源于stack exchange,提问作者Thraetaona
相关产品推荐
相关产品推荐

