C++文件的输入输出问题

今天写这篇博客纯粹就是遇到点问题,不知道有没有人遇到过。

背景

最近打CF的时候发现交上去一个答案发生了非预期退出,而且是在样例里面发生的,于是我赶紧把程序扒下来最大限度地确定出现问题的代码段,最终出现了以下代码写的程序。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include<bits/stdc++.h>
using namespace std;
int main(){
freopen("1.in","r",stdin);
ios::sync_with_stdio(false);
long long q;
cin>>q;
while(q--){
long long s,t;
scanf("%lld %lld",&s,&t);
printf("s=%lld t=%lld\n",s,t);

}

return 0;
}

首先万能头文件,然后我打开了一个文件把标准输入流重定向到一个文件中,并且关闭了 $cin$ 和 $cout$ 的同步流,大概率问题是出在这里的,然后就一些常规操作没什么好说的。

我的 $1.in$ 的文件内容如下图所示:

1

是正常的输入数据,并且文件编码为 $UTF-8$ 没有任何问题。

测试

那么我们开 $DEV$ 运行以下先。

2

可以看到程序运行出现了非预期结果。

由于 $DEV$ 不方便调试我们便把 $IDE$ 换成了 $VScode$ 。

这里我们在 $scanf$ 和 $printf$ 分别打一个断点,然后开启调试模式。

3

这里 $s$ 和 $t$ 是随机值正常,因为我们并没有初始化 $s$ 和 $t$ 。

那么我们 $F10$ 步过看看结果。

4

过了 $scanf$ 却没有成功读入数据!!!这是为什么?

我开始尝试找不同的原因,原因1就是怀疑文件读入的问题,所以我们先注释重定向那一行测试看看。

5

运行结果是正常的,这么看来问题似乎解决了。

但是提交给oj是实实在在地报错了,因此我们尝试注释其它代码看看情况,这里我们接着选择注释这个关闭同步流的代码。

6

这回居然正常读入了数据!什么鬼?

因为刚刚我把 $freopen$ 注释了是确确实实读入没有什么问题了,但是现在似乎把

1
ios::sync_with_stdio(false);

给关闭了程序也是能正常进行的。

而且这里我还测试了第三种情况:两者都打开,把 $long long$ 换回 $int$ 类型。

7

居然也是正常读入?也就是说,打开文件,在关闭同步流的情况下使用 $scanf$ 读入 $long long$ 数据类型会导致读入不成功,而且注释了打开文件提交给 oj 测评返回了错误结果。

总结

我个人感觉可能涉及到底层的一些问题了。因为自己测试确实三种情况同时满足会导致读入数据失败。这三种情况分别是

  1. 重定向 $stdin$ 到一个文件
  2. 关闭IO同步流
  3. 用 $scanf$ 读入 $long long$ 数据

一般来说,$scanf$ 不接收到 $EOF$ 信号是会一直等待你输入的。常见的 $EOF$ 基本就是读到文件尾,或者手动给终端了一个 $Ctrl + Z$ 信号给程序,这应该算外部中断了。就基本不会遇到 $scanf$ 读入失败的情况。要真的能有这么好数据那不是可以随便泄露?如果上一个栈帧保存的一些变量的地址刚好在这,我这里故意读入失败那就直接泄露地址,我没见过这样的情况。

当然我比较浅薄,只能看到表面上的一些东西,如果你有深层次点的合理的解释麻烦你也联系我,我也不想就在这里留一个错误的结论,期待这个问题能早点解决。

下面我也给出以下本次实验用到的附件供大家测试,看看能不能是版本的问题。

文章目录
  1. 1. 背景
  2. 2. 测试
  3. 3. 总结
|