【问题标题】:Why am I getting different outputs for the same code? [closed]为什么我会为相同的代码获得不同的输出? [关闭]
【发布时间】:2021-03-23 10:22:47
【问题描述】:
#include <stdio.h>

typedef struct {
  int x,y;
} point;

point* create_point(int x,int y) {
  point p={x,y};
  point* ptr = &p;
  return ptr;
}

int main() {
  point* p1 = create_point(1,2);
  point* p2 = create_point(6,7);
  printf("%d, %d, ", p1->x, p1->y);
  printf("%d, %d \n", p2->x, p2->y);
  return 0;
}

当我使用 repl.it 编译时,我得到 6,7,0,0 作为输出,但是当我使用 sublime 文本编辑器运行相同的程序时,我得到不同的输出:6,7,6,7。有谁知道为什么?哪个输出是正确的输出?任何帮助表示赞赏,谢谢。

【问题讨论】:

  • 为什么会得到输出?任何地方都没有printf()
  • p1 = &amp;p; 是无用的语句,因为p1 是函数范围内的指针。参考“传值”。
  • 嗯,你正在设置(并返回)ptr 到自动变量的地址(p),当函数返回时,它将超出范围,所以这是 UB。跨度>
  • 考试明确表示:不允许在线发布问题寻求解决方案

标签: c debugging output repl.it


【解决方案1】:

通常,当您有一个“工厂”函数创建并返回一个指向对象的指针时,该对象应该使用malloc() 在堆上分配,如下所示:

int *factory(){
    int *p;
    p = malloc(sizeof(whatever));
    return p;
    }

在 C 中,函数返回是按值的。在这种情况下,虽然p 是一个本地的、堆栈分配的变量,但它是一个指针,它的值(这是传回给调用者的值)将是malloc() 返回的堆分配对象的地址所以它是函数范围之外的一个有意义的值。

在您的函数create_point() 中,您正在返回一个指针,但因为p 是一个本地(自动)变量,它是在堆栈上分配的,因此您返回的指向它的指针将引用create_point() 的堆栈帧中的地址。根据给定的编译器如何在堆栈上排序自动变量(以及您访问它们的顺序)以及它需要根据 ABI 放置在那里的其他信息,您可能很幸运并收到了您预期的结果,如果你只调用了一次create_point(),你永远不会检测到这个错误。但是第二次调用的堆栈帧可能与第一次调用的堆栈帧在进程堆栈上的位置相同或重叠,这意味着第一次调用留下的部分或全部内容(因为函数调用的堆栈帧一旦函数返回通常不会被清除,旧值仍然存在,直到这些内存位置被覆盖)将被第二次调用 create_point() 以及随后调用 printf(). 破坏

【讨论】:

    猜你喜欢
    • 2019-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-31
    • 1970-01-01
    • 1970-01-01
    • 2022-01-04
    相关资源
    最近更新 更多