为什么这个指针在 g++ 之间的行为不同?和 Visual Studio 2022 的编译器?

发布于 2025-01-14 06:05:41 字数 1034 浏览 2 评论 0原文

编辑:我的问题与编译器之间的差异有关,但我只是被误导认为当两个编译器实际上都显示预期的“未定义行为”时存在不同的行为

我知道在这里使用 static 关键字对于building_num整数有好处,但我不明白为什么在用 g++ 编译时正确打印该值,我认为在 allocate_building_num 函数终止后应该删除整数值

使用 Visual Studio 的编译器我看到了我假设的行为,它不打印出来400,它打印出一些随机数(在本例中由于某种原因它总是 32759)

#include <iostream>
#include <string>

using namespace std;

class building {
    int* ptr_building_num;

public:
    void set_building_num(int* num_ptr) {
        ptr_building_num = num_ptr;
    }

    void print_building() {
        cout << *ptr_building_num << flush;
    }
};

void assign_building_num(building* building_ptr) {
    //int* ptr_to_building_num = nullptr;
    int building_num = 400;
    int* ptr_to_building_num = &building_num;

    building_ptr->set_building_num(ptr_to_building_num);
}

int main() {
    building* ptr_to_some_building = nullptr;
    ptr_to_some_building = new building;

    assign_building_num(ptr_to_some_building);

    ptr_to_some_building->print_building();

    return 0;
}

Edit: my question was relating to the difference between compilers but I was just mislead to think there was different behavior when really both compilers were showing the expected "undefined behavior"

I know that using the static keyword here would be good for the building_num integer, but I don't understand why the value prints correctly when compiling with g++, I would think the integer value should be erased after the assign_building_num function terminates

With visual studio's compiler I see the behavior I assume, where it doesn't print out 400, it prints out some random number (in this case it is always 32759 for some reason)

#include <iostream>
#include <string>

using namespace std;

class building {
    int* ptr_building_num;

public:
    void set_building_num(int* num_ptr) {
        ptr_building_num = num_ptr;
    }

    void print_building() {
        cout << *ptr_building_num << flush;
    }
};

void assign_building_num(building* building_ptr) {
    //int* ptr_to_building_num = nullptr;
    int building_num = 400;
    int* ptr_to_building_num = &building_num;

    building_ptr->set_building_num(ptr_to_building_num);
}

int main() {
    building* ptr_to_some_building = nullptr;
    ptr_to_some_building = new building;

    assign_building_num(ptr_to_some_building);

    ptr_to_some_building->print_building();

    return 0;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

恋你朝朝暮暮 2025-01-21 06:05:41

一旦作用域退出,在作用域中声明的变量(在本例中,building_num 的作用域是函数assign_building_num 的主体)就不再存在。

您正在获取一个生命周期很短的整数的地址,并在对象被销毁后保留其地址。

从指针读取已销毁对象是未定义行为,因此两个编译器都是正确的。

您的构建对象所保存的地址的整数必须至少与构建对象本身一样长

编辑:
由于出现了“未定义行为”问题,为了完整起见,cppreference 对此是这么说的:

未定义的行为 - 对行为没有限制
程序。未定义行为的示例包括数据争用、内存
访问数组边界之外、有符号整数溢出、null
指针取消引用,对同一标量进行多次修改
没有任何中间序列点的表达式(直到
C++11) 是无序的 (C++11 起),通过
不同类型的指针等。编译器不需要
诊断未定义的行为(尽管许多简单的情况是
诊断),编译后的程序不需要做任何事情
有意义。

Variables declared in a scope (in this case, the scope for building_num is the body of the function assign_ building_num) cease to exist once the scope exits.

You are taking the address of an integer that only has a short lifetime, and retaining its address after the object has been destroyed.

Reading from a pointer to a destroyed object is Undefined Behavior, so both compilers are correct.

The integer whose address that your building object holds must live at least as long as the building object itself.

EDIT:
Since a question Undefined Behavior came up, here's what cppreference says about it, for completeness:

undefined behavior - there are no restrictions on the behavior of the
program. Examples of undefined behavior are data races, memory
accesses outside of array bounds, signed integer overflow, null
pointer dereference, more than one modifications of the same scalar in
an expression without any intermediate sequence point (until
C++11)that is unsequenced (since C++11), access to an object through a
pointer of a different type, etc. Compilers are not required to
diagnose undefined behavior (although many simple situations are
diagnosed), and the compiled program is not required to do anything
meaningful.

夏九 2025-01-21 06:05:41

您编写了一些非常非常复杂的代码,最终将“building.ptr_building_num”设置为指向

   void assign_building_num(building* building_ptr) {
    //int* ptr_to_building_num = nullptr;
       int building_num = 400;              <<<<===== this value here
    int* ptr_to_building_num = &building_num;

    building_ptr->set_building_num(ptr_to_building_num);
}

无效。因为一旦该函数结束该变量就会消失。通常 VS 或 GCC 会警告你这一点,但你已经做了足够多的杂耍,他们看不到你正在这样做。

为什么有时有效,有时却无效。因为您调用了未定义行为,所以结果可以是任何结果。在我的 VS 系统上,我得到了 400。

但是如果我将代码更改为

assign_building_num(ptr_to_some_building);

cout << "test test\n"; <<== add this

ptr_to_some_building->print_building();

,那么我会得到

test test
-858993460

It isn'tclear you 实际上想要做什么。如果您希望构建指向一个整数(为什么?),那么您需要将该整数分配到稳定的地方。

您暗示 'static' ,这肯定会起作用

void assign_building_num(building* building_ptr) {
    //int* ptr_to_building_num = nullptr;
    static int building_num = 400; <<<=======================
    int* ptr_to_building_num = &building_num;

    building_ptr->set_building_num(ptr_to_building_num);
}

,但这是一件非常奇怪的事情,所有构建实例最终都会指向相同的整数。也许这就是你想要的。很难说。否则在堆上分配。或者,如果它只是一个整数,则将其放入构建对象中

You have made some very , very convoluted code that ends up setting 'building.ptr_building_num' to point at

   void assign_building_num(building* building_ptr) {
    //int* ptr_to_building_num = nullptr;
       int building_num = 400;              <<<<===== this value here
    int* ptr_to_building_num = &building_num;

    building_ptr->set_building_num(ptr_to_building_num);
}

THats not valid. Because that variable will disappear once that function ends. Normally VS or GCC would warn you about this but you have done enough juggling that they cant see that you are doing that.

Why does it work sometimes and not others. becuase you have invoked Undefined Behavior, the result can be anything. On my VS system I got 400.

But if I change the code to

assign_building_num(ptr_to_some_building);

cout << "test test\n"; <<== add this

ptr_to_some_building->print_building();

then I get

test test
-858993460

Its not clear what you actually want to do. If you want building to point to an integer (why?) then you need to allocate that integer somewhere stable.

You hint at 'static' , this will certainly work

void assign_building_num(building* building_ptr) {
    //int* ptr_to_building_num = nullptr;
    static int building_num = 400; <<<=======================
    int* ptr_to_building_num = &building_num;

    building_ptr->set_building_num(ptr_to_building_num);
}

but is a very odd thing to do, all building instances will end up pointing to the same integer. Maybe thats what you want. Hard to say. Otherwise allocate on the heap. Or if it just one integer put it in the building object

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文