#include <iostream>
using namespace std;
struct A{
const char* a;
};
void f(A* a){
string s("abc");
a->a = s.c_str();
}
int main(int argc, char* argv[]){
A a;
f(&a);
printf("a: %s\n", a.a);
return 0;
}
这属于 ub 的问题吗?
1
zwzmzd 2018-09-19 09:27:26 +08:00 via iPhone
s 都随着函数 f 结束销毁了,再去用 c_str 本身就有问题
|
3
ai277014717 2018-09-19 09:42:33 +08:00
编译器内部实现不一样造成的吧
|
4
seancheer 2018-09-19 09:46:13 +08:00
@zynlp 内存释放并不代表那块内存里面的内容会被写成 0,只是说这块内存可以被其他代码使用了。。你这个时候访问一块已经释放的内存虽然这会儿正常,但是不保证过一段时间还是正常的。。当程序规模比较大的时候,这块内存很有可能很快就被其他代码段使用了。
这就是传说中踩内存中的一种情况。 |
5
liangweijia6000 2018-09-19 09:49:13 +08:00 1
这是想研究啥。。
|
6
zivyou 2018-09-19 09:49:45 +08:00
会不会不同平台的垃圾清理方式不同导致的?比如 windows 中,在函数调用完之后,该函数的局部变量就被清理;而 Linux 将这个动作延迟到了进程退出(只是一种推测,我没有证实过)。
|
7
dynamicheart 2018-09-19 09:50:16 +08:00 via iPhone
@zynlp 在 Linux 下,离开 f 作用域后,s 被销毁了,a 指向的是一个无效的地址空间,但因为这段内存空间还没有被复用,里面的数据还是 abc,所以打印出来的是 abc。
|
9
disk 2018-09-19 09:51:51 +08:00 via Android
别这样,vs 安全检查比较严格,你不知道什么时候悬空
|
10
wdlth 2018-09-19 09:55:07 +08:00
我在 Linux 下执行是返回乱码
|
11
ipwx 2018-09-19 10:02:55 +08:00
这是未定义行为吧,你去理解它没有意义。
|
12
Rosanta 2018-09-19 10:13:37 +08:00
UB 有啥好研究的,你开不一样的优化等级输出还不一样呢
|
13
rocbomb 2018-09-19 10:13:54 +08:00
想起了大一 C 语言课本上的 a=(i++)*(i++)*(i++)*(i++)*(i++)*(i++);
这种代码在工作中 谁写出来我非打死他不可 |
14
seancheer 2018-09-19 10:14:27 +08:00
@zynlp 不一定啊。。和具体实现相关。具体就要找下 vc 和 linux 下的实现区别了。不过个人觉得死磕这个没有意义。
你代码本身就是错误的行为,真正系统下是肯定会出问题的,无论 vc 还是 g++ |
15
sbw 2018-09-19 11:36:03 +08:00
学习一下 Rust 你就知道
|
18
429839446 2018-09-19 14:19:08 +08:00
请看 cppreference, c_str()这样用是未定义行为.
|
19
shilyx 2018-09-19 14:20:32 +08:00
一楼说得对,代码错了,这是前提。
错了的代码输出什么,只能回答:是什么就是什么,无任何保证。 你汇编跟踪以下,也能搞清楚为什么会那样输出,一句话,各有各的道理,编译器不背锅。 |
20
nutting 2018-09-19 14:29:24 +08:00
g++ (GCC) 4.8.5 20150623 (Red Hat 4.8.5-16),编译不过去
Apple LLVM version 7.3.0 (clang-703.0.29),编译后运行,输出乱码 |
21
tourist2018 2018-09-19 15:15:34 +08:00
@zivyou #6 和操作系统应该没关系 和编译器有关系 而且可以直接使用 printf 方法么?这不是 stdio.h 里面的库函数?
|
22
wwqgtxx 2018-09-19 17:49:44 +08:00
@tourist2018 有些编译器的 iostream 文件中会导入 cstdio 所以可以直接用
|
23
neptuno 2018-09-19 17:59:24 +08:00
编译器不一样。有些未定义行为在不同编译器不一样的
|
24
iceheart 2018-09-19 23:17:02 +08:00 via Android
这不是 ub,这是野指针
|
25
msg7086 2018-09-20 00:34:50 +08:00
刚想说,这就是野指针啊。(然后楼上说了。)
随便指向内存中一块不属于你的地址,出来的是啥就是啥。 如果内核看你不爽,可以直接杀掉你的进程。如果他没那么凶,那就让你随便读点内存里的辣鸡数据。 |