为什么这个指针在 g++ 之间的行为不同?和 Visual Studio 2022 的编译器?
编辑:我的问题与编译器之间的差异有关,但我只是被误导认为当两个编译器实际上都显示预期的“未定义行为”时存在不同的行为
我知道在这里使用 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 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
一旦作用域退出,在作用域中声明的变量(在本例中,
building_num
的作用域是函数assign_building_num
的主体)就不再存在。您正在获取一个生命周期很短的整数的地址,并在对象被销毁后保留其地址。
从指针读取已销毁对象是未定义行为,因此两个编译器都是正确的。
您的构建对象所保存的地址的整数必须至少与构建对象本身一样长。
编辑:
由于出现了“未定义行为”问题,为了完整起见,cppreference 对此是这么说的:
Variables declared in a scope (in this case, the scope for
building_num
is the body of the functionassign_ 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:
您编写了一些非常非常复杂的代码,最终将“building.ptr_building_num”设置为指向
无效。因为一旦该函数结束该变量就会消失。通常 VS 或 GCC 会警告你这一点,但你已经做了足够多的杂耍,他们看不到你正在这样做。
为什么有时有效,有时却无效。因为您调用了未定义行为,所以结果可以是任何结果。在我的 VS 系统上,我得到了 400。
但是如果我将代码更改为
,那么我会得到
It isn'tclear you 实际上想要做什么。如果您希望构建指向一个整数(为什么?),那么您需要将该整数分配到稳定的地方。
您暗示 'static' ,这肯定会起作用
,但这是一件非常奇怪的事情,所有构建实例最终都会指向相同的整数。也许这就是你想要的。很难说。否则在堆上分配。或者,如果它只是一个整数,则将其放入构建对象中
You have made some very , very convoluted code that ends up setting 'building.ptr_building_num' to point at
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
then I get
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
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