使用__builtin_va_arg_pack()编译失败,如何排查解决?
链接错误:undefined reference to
myprintf 原因及解决 问题场景
出于纯教学目的,尝试使用GCC的「构造函数调用内置函数」编写示例,实现代码如下:
#include <stdio.h> extern int myprintf(FILE *f, const char *format, ...); extern inline __attribute__((__gnu_inline__)) int myprintf(FILE *f, const char *format, ...) { int r = fprintf(f, "myprintf: "); if (r < 0) return r; int s = fprintf(f, format, __builtin_va_arg_pack()); if (s < 0) return s; return r + s; } int main() { myprintf(stdout, "ciao %d\n", 10); return 0; }
执行编译命令gcc -std=gnu2x -Wall test1.c -o test1时,出现链接错误:
/usr/bin/ld: /tmp/ccgD1BYT.o: in function `main': test1.c:(.text+0x27): undefined reference to `myprintf' collect2: error: ld returned 1 exit status
使用GCC版本为Ubuntu 13.2.0-4ubuntu3。
问题原因
问题出在extern inline与__gnu_inline__属性的组合逻辑上:
- 当使用
extern inline __attribute__((__gnu_inline__))时,GCC遵循GNU扩展的inline规则:编译器只会尝试将该函数内联到调用处,不会在当前编译单元生成该函数的外部可见定义,而是假设这个函数的定义会在其他编译单元中提供。 - 但代码中仅提供了这一个inline版本的实现,没有其他地方的非inline定义,因此链接器找不到
myprintf的符号,抛出未定义引用错误。
解决方法
方法1:移除extern关键字
去掉函数声明和定义中的extern,仅保留inline __attribute__((__gnu_inline__)),这样GCC会在当前编译单元中生成该函数的本地定义(当无法内联时),同时支持内联展开:
#include <stdio.h> inline __attribute__((__gnu_inline__)) int myprintf(FILE *f, const char *format, ...) { int r = fprintf(f, "myprintf: "); if (r < 0) return r; int s = fprintf(f, format, __builtin_va_arg_pack()); if (s < 0) return s; return r + s; } int main() { myprintf(stdout, "ciao %d\n", 10); return 0; }
方法2:保留extern并补充外部定义
如果需要保留extern inline的写法,需要单独提供一个非inline的myprintf实现(可以放在同一个文件或其他编译单元),例如:
#include <stdio.h> // 声明+inline定义 extern int myprintf(FILE *f, const char *format, ...); extern inline __attribute__((__gnu_inline__)) int myprintf(FILE *f, const char *format, ...) { int r = fprintf(f, "myprintf: "); if (r < 0) return r; int s = fprintf(f, format, __builtin_va_arg_pack()); if (s < 0) return s; return r + s; } // 补充外部定义 int myprintf(FILE *f, const char *format, ...) { int r = fprintf(f, "myprintf: "); if (r < 0) return r; int s = fprintf(f, format, __builtin_va_arg_pack()); if (s < 0) return s; return r + s; } int main() { myprintf(stdout, "ciao %d\n", 10); return 0; }
内容的提问来源于stack exchange,提问作者mastupristi
相关产品推荐
相关产品推荐

