【问题标题】:Function returns intended value even without the return statement即使没有 return 语句,函数也会返回预期值
【发布时间】:2014-09-05 03:44:41
【问题描述】:

我这里有一个函数get_stack,它实例化一个堆栈并应该返回一个指向堆栈的指针,但没有。尽管如此,程序仍会继续并正确更新堆栈。

#include <stdio.h>
#include <stdlib.h>    
#define STACKLIM 1000


struct stack {
    char data[STACKLIM];
    int top;
};

typedef struct stack* Stack;

Stack get_stack() {
    Stack s = (Stack)(malloc(sizeof(struct stack)));
    s->top = -1;
    //return s;
}

void push(Stack s, char val) {
    if(s->top == STACKLIM) {
        printf("ERROR: Stack Overflow\n");
    }
    else {
        s->top += 1;
        s->data[s->top] = val;
    }
}

void display(Stack s) {
    int i;
    printf("Stack -> ");
    for(i = 0; i <= s->top; i++) {
        printf("%c ", s->data[i]);
    }
    printf("\n");
}

int main() {
    Stack d = NULL;
    d = get_stack();
    push(d, 'a');
    display(d);        
    return 0;
}

这就像return语句无关紧要。这可能是什么原因?我在 RH5 机器上使用 gcc 4.5.2。

【问题讨论】:

  • 使用-Wall 编译时会发生什么?另外,请查看此链接:stackoverflow.com/questions/10079089/…
  • 您是否使用了任何优化标志?请记住,未定义的行为包括让您的程序神秘地工作。
  • 当我使用-Wall 编译时,我得到了warning: control reaches end of non-void function,但程序仍然可以正常运行。
  • 请记住,您已经定义了Stack get_stack(),因此get_stack() 被声明为返回类型struct stack * 的函数——您只是缺少定义中的return 语句。我和hugomg 和AntonH 在一起。你已经被UB祝福了。
  • 这是一个完全正常的意外。按照惯例,函数的返回值通过 CPU 寄存器传回。就像英特尔处理器的 EAX 一样。该寄存器很可能会意外包含指针,尤其是当您不打开优化器时。

标签: c


【解决方案1】:

无论编译器是否诊断它,如果函数具有非void 返回类型,则从函数末尾(即到达关闭})而不返回值始终是错误的。这是未定义的行为

现在,未定义的行为可以以多种不同的方式表现出来。它可能导致您的程序崩溃、接收错误的值、擦除您的硬盘驱动器、向您的母亲发送一封令人讨厌的电子邮件,或者看起来可以正常运行而没有其他不良影响。 C 语言标准允许所有这些行为。仅仅因为代码看起来可以正常工作,并不意味着它实际上是正确的并且可以工作。

如果您在调用未定义行为时崩溃,您应该认为自己很幸运,因为这些通常很容易诊断。但是,如果您的程序默默地破坏内存,然后在“不可能”的情况下崩溃,那么您将面临一项艰巨的调试工作。

故事的寓意:以高警告级别编译您的代码(例如,使用-Wall 编译器选项;如果可以忍受,也可以使用-Wextra 和/或-pedantic;强烈推荐-Werror) .任何称职的编译器都会捕获这种错误,但通常不会处于默认警告级别

【讨论】:

  • 我似乎记得有一个编译器,在一个未定义行为的情况下,启动了Snake 的游戏,或者类似的东西。希望我能找到参考...
  • @AntonH:它不完全是 Snake,而是足够高级的编译器 can cause time travel when they detect undefined behavior — 如果他们能够推断出某些条件最终会触发 UB,他们可以积极优化掉原本会被定义为行为的代码.
【解决方案2】:

之前回答过:Function returns value without return statement

它的要点:当执行 d = get_stack() 时,系统会查看内存中它期望找到返回值的某个位置。记忆中那个地方的任何垃圾 - 都算作回报。

它可能是那个“eax 寄存器”或调用堆栈中的一个槽。你很幸运 malloc() 的返回卡在那个地方。在 get_stack() 中添加一些额外的命令,奇迹就会消失。

【讨论】:

    猜你喜欢
    • 2013-04-29
    • 1970-01-01
    • 2011-04-13
    • 1970-01-01
    • 2018-11-20
    • 1970-01-01
    • 2013-12-22
    • 2011-06-06
    相关资源
    最近更新 更多