未定义_GNU_SOURCE时GNU扩展功能如何运行

时间:2018-11-13 09:13:56

标签: gcc compilation gnu cpu-architecture glibc

我在不同平台上测试了GNU扩展功能,例如“ wcstoq”。 一开始,我没有使用D_GNU_SOURCE编译测试用例,所以得到了如下编译警告:

wcstoq.c:31:12: warning: implicit declaration of function 'wcstoq'; did you mean 'wcstol'? [-Wimplicit-function-declaration]
     retval=wcstoq(nptr,endptr,base);
            ^~~~~~
            wcstol

当我使用gdb调试此测试用例时,它进入与我定义_GNU_SOURCE的情况相同的正确函数。 但是当我没有定义_GNU_SOURCE时,该函数就会出错。

例如:

当我在x86_64中测试超出范围的情况时,应设置retval= LLONG_MAX(0x7FFFFFFFFFFFFFFF),但实际上应设置retval= -1(0xFFFFFFFFFFFFFFFF)。 当我在其他平台ppc上进行测试时,结果也使我感到困惑,它实际上设置了retval=0x000000007FFFFFFF。 当我定义_GNU_SOURCE时,函数在x86_64和ppc中运行正常,它们都返回LLONG_MAX(0x7FFFFFFFFFFFFFFF)

我的问题是:

1为什么当我没有定义_GNU_SOURCE时,gcc仍然可以找到正确的函数?

2为什么即使gcc找到正确的功能,功能也失败了,在某些情况下仍可以使用该功能,但在其他情况下却出错了?

3为什么功能失败的结果在不同的平台上是不同的,架构平台或其他因素如何影响不同的结果?

4使用GNU扩展功能的正确方法?

谢谢!

1 个答案:

答案 0 :(得分:1)

隐式函数声明是默认启用的GCC扩展,它使用返回类型int,但是该函数定义为返回long long。由于这种类型的不匹配,任何事情都可能发生。在实践中,结果取决于调用约定,这就是为什么它们在体系结构之间有所不同的原因。

您应该真正使用-Werror=implicit-function-declaration进行编译(或使用C ++)。隐式函数声明是在20年前(在ISO / IEC 9899:1999中)从C中删除的,但是我们仍然不能更改GCC默认值,因为太多的autoconf检查会中断,从而导致软件意外丢失功能。

(我想您是在问题中写retval而不是errno。)