It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center
6年前关闭。
我只花了半天时间来计算x86-64代码中的一个细微崩溃,所以这是一个向其他人的提醒-我在其他地方没有见过这种处理。
如果在没有正确声明的情况下使用libc函数,gcc将假定它返回int。例如,setlocale()被假定为int setlocale(),EAX中返回32位int值。
尝试通过隐式或显式转换将此返回转换为指针,将通过符号扩展强制从32位转换为64位,即使调用的函数在RAX中返回有效的64位指针值!例如。
    char *p = setlocale(0, 0);      // bear with me for a second

被编译为
    1c: b8 00 00 00 00          mov    $0x0,%eax
    21: e8 00 00 00 00          callq  26 <hard_locale+0x26>
    26: 48 98                   cltq   ;   <--- eax is expanded in rax

海合会甚至试图告诉你:
    warning: initialization makes pointer from integer without a cast

如果添加显式强制转换,则警告将更改为,这将显示问题:
    warning: cast to pointer from integer of different size

如果幸运的话,什么都不会发生,但是如果它碰巧为内存中向上的指针返回一个较大的值,那么它将被弄乱,如下所示:
    function returns in RAX: 0x07ffff7b9705e
    cltq considers EAX with negative sign: 0xf7b9705e
    now RAX is: 0xfffffffff7b9705e

你的指针无效。
修复和解决方案:
始终使用正确的函数声明
-在x86-64编译器中,Wall-Werror应该是默认的。

最佳答案

未声明的函数不是有效的C。只需添加-Werror=implicit-function-declaration,问题就会消失。你不需要把其他的警告(主要是三段论的考虑)变成错误。
下面是一个警告列表,作为GCC拒绝无效C而不出现任何误报的错误选项。它漏掉了一些东西(GCC不支持捕获),但它基本上是完整的:
-Werror=implicit-function-declaration
-Werror=implicit-int
-Werror=pointer-sign
-Werror-pointer-arith
-Werror=return-type
-std=c99(或-std=c11等,根据需要)
-pedantic-errors(可选;拒绝某些有效但不完全可移植的代码)
注意,我最初也将-Werror=sequence-point-Werror=array-bounds添加到列表中,但它们有误报,因为它们不标记约束冲突,只标记运行时UB。因此,只要调用UB的代码是不可访问的,包含此类警告的程序仍然可以是正确的程序(作为一个很好的例子,可以考虑if (sizeof(int)==sizeof(long)) { ... } else { ... }这样的分支,其中未执行的分支基于sizeof运算符的结果调用UB)。

07-28 04:17