为什么这个编译没有错误?为什么它运行在32位机器上而不是64位?

时间:2014-05-09 21:53:13

标签: c gcc

我可以使用-Wextra -g标志用gcc编译它,我没有错误。为什么编译器没有注意到我没有从非void函数返回任何东西?另外,我在32位和64位机器上运行它。它在32位,甚至印刷的苹果干长度10上运行得非常好。苹果颜色r'但它在64位机器上出现故障。 gcc在这里做什么给了我不可预测的行为,为什么它在编译时没有给我任何错误?

#include <stdlib.h>
#include <stdio.h>

struct apple
{
    int stem_length;
    char color;
};

struct apple* alloc_apple(const int stem_length, const char color)
{
    struct apple* new_apple = (struct apple*)malloc(sizeof(struct apple));
    new_apple->stem_length = stem_length;
    new_apple->color = color;
}

int main(int argc, char* argv[])
{
    struct apple* some_apple = alloc_apple(10, 'r');
    printf("Apple stem length %d. Apple color %c\n", some_apple->stem_length,
        some_apple->color);

    free(some_apple);
    return 0;
}

4 个答案:

答案 0 :(得分:4)

alloc_apple最后未return new_apple;。如果new_apple恰好留在寄存器中,当函数返回时(在i386上这通常是EAX)预期返回值,这可能会巧合,但允许控制到达终点非void返回函数的行为产生未定义的行为(可能包括意外按预期工作到causing demons to fly out of your nose的任何内容)。

我相当肯定,如果你用gcc -Wall编译(启用所有警告),它会指出问题; return-type是具体警告。

如果没有return,则使用古老的返回表达式的值的编译器的函数甚至不起作用,因为最后一个表达式的计算结果为color的值

答案 1 :(得分:3)

您正在使用-Wextra,但这是错误的选择。

Gcc(以及大多数unix编译器)使用-Wall选项启用大多数警告,包括您要查看的警告,-Wreturn-typehttp://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html

  

-Wall

     

这将启用有关某些用户认为有问题且易于避免(或修改以防止警告)的构造的所有警告,即使与宏结合使用也是如此。   -Wall打开以下警告标志:

     

... -Wreturn-type列表以及另外30个-W...标记

-Wextra仅启用了-Wall未启用的其他几个警告。

  

-Wextra

     

这会启用一些未被-Wall启用的额外警告标志。   ... 12个罕见的-W...选项列表

示例:

$ gcc t.c -Wextra
# No output
$ gcc t.c -Wall
t.c: In function ‘alloc_apple’:
t.c:15:1: warning: control reaches end of non-void function [-Wreturn-type]
 }
 ^

所以,只需使用&#34; -Wall&#34;得到大多数警告,-Wall -Wextra以获得更多。有时你也可以使用set -Wall -Wextra -std=c99 -pedantic -pedantic-errors来确保你的程序非常接近C99标准(但是系统头文件有非标准代码而且没有被捕获)。

同样使用clang,它有更好的警告和默认设置的更好警告:

$ clang t.c
t.c:15:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
1 warning generated.

答案 2 :(得分:0)

问题是您无法从函数返回值。

这是未定义的行为。它只是“似乎工作”在32位,它崩溃在64位。如果您对为什么失败感到好奇,那么第一步就是获得堆栈跟踪。

至于“GCC为什么不告诉我?”

它可以:

  

http://gcc.gnu.org/onlinedocs/gcc-3.4.3/gcc/Warning-Options.html

     

-Wreturn型

     

每当使用默认为int的返回类型定义函数时发出警告。还警告任何没有的退货声明   返回类型不为void的函数的返回值。

     

对于C ++,即使指定了 -Wno-return-type ,没有返回类型的函数也会产生诊断消息。唯一的   例外是系统头中定义的主要和函数。

就个人而言,我几乎总是在开发过程中使用这些开关:

gcc -g -pedantic -Wall ...

答案 3 :(得分:0)

错误?什么错误?

“不从非空函数返回任何内容”从未被认为是C中的正式“错误”(即约束违规)。(顺便说一下,它也不是C ++中的“错误”)。这就是语言的定义方式。某些编译器可能会发出警告,但在一般情况下,不允许将其视为违反约束。

作为旁注,C和C ++在这方面的区别在于,在C ++中忘记返回某些东西总是未定义的行为。在C中,只有当您尝试在调用代码中使用函数的结果时,行为才是未定义的。否则,如果调用者忽略返回的值,则C将其视为完全正常的合法代码。