std::ofstrean 不适用于 -O3
std::ofstrean doesn't work with -O3
下面的代码,简单
1) 从命令行参数中获取输入文件名,比如 in.txt
2) 将文件名附加到 "cdf_"
3) 打开一个新名称的文件 cdf_in.txt
4) 简单地读取每一行(每行一个数字)并将其发送到输出文件。
#include <iostream>
#include <fstream>
#include <cstring>
using namespace std;
int main(int argc, char* argv[])
{
char *ben = argv[1]; // example: in.txt
ifstream fin (ben);
char res[30];
char *o1 = "cdf_";
strcat(res, o1);
strcat(res, ben);
ofstream fout (res, std::ofstream::out); // will be cdf_in.txt
cout << res << endl;
uint64_t num; uint64_t sum = 0;
while (fin >> num) {
fout << num << endl;
}
return 0;
}
通过运行程序没有任何优化,运行正常。但是,通过指定 -O3
,它无法创建输出文件。为什么???
$ g++ -o cdf cdf.cpp
cdf.cpp: In function ‘int main(int, char**)’:
cdf.cpp:19: warning: deprecated conversion from string constant to ‘char*’
$ ./cdf in.txt
cdf_in.txt
$ ls cdf*
cdf cdf.cpp cdf_in.txt cdf.py
$ cat cdf_in.txt
10
5
3
2
1
$ rm cdf_in.txt
$ g++ -O3 -o cdf cdf.cpp
cdf.cpp: In function ‘int main(int, char**)’:
cdf.cpp:19: warning: deprecated conversion from string constant to ‘char*’
$ ./cdf in.txt
cdf_in.txt
$ ls cdf*
cdf cdf.cpp cdf.py
为什么 fout
不适用于 -O3
?
您的 strcat(res, o1);
取决于 res[0] == '[=13=]'
,这可能是正确的,但不能保证(res
是未初始化的本地,因此其内容不是 known/specified).
有可能在您不进行优化时将其初始化为零,但在您进行优化时则不会。
您可以通过初始化 res
或使用 strcpy
而不是 strcat
来修复您要复制到那里的第一个项目(但这仍然会留下可能的缓冲区溢出问题,所以请参阅下文以获得更好的选择)。
或者,当然,您可以编写更像 C++ 而不是 C 的代码,并使用 std::string
而不是 char 数组。
std::string fname("cdf_");
fname += argv[1];
std::ofstream fout(fname.c_str()); // just `fout(fname)` with a C++11 compiler
如果您出于某种原因真的想编写类似 C 的代码,在这种情况下使用 sprintf
可能更容易:
char res[30];
sprintf(res, "cdf_%35s", argv[1]);
std::ofstream fout(res);
下面的代码,简单
1) 从命令行参数中获取输入文件名,比如 in.txt
2) 将文件名附加到 "cdf_"
3) 打开一个新名称的文件 cdf_in.txt
4) 简单地读取每一行(每行一个数字)并将其发送到输出文件。
#include <iostream>
#include <fstream>
#include <cstring>
using namespace std;
int main(int argc, char* argv[])
{
char *ben = argv[1]; // example: in.txt
ifstream fin (ben);
char res[30];
char *o1 = "cdf_";
strcat(res, o1);
strcat(res, ben);
ofstream fout (res, std::ofstream::out); // will be cdf_in.txt
cout << res << endl;
uint64_t num; uint64_t sum = 0;
while (fin >> num) {
fout << num << endl;
}
return 0;
}
通过运行程序没有任何优化,运行正常。但是,通过指定 -O3
,它无法创建输出文件。为什么???
$ g++ -o cdf cdf.cpp
cdf.cpp: In function ‘int main(int, char**)’:
cdf.cpp:19: warning: deprecated conversion from string constant to ‘char*’
$ ./cdf in.txt
cdf_in.txt
$ ls cdf*
cdf cdf.cpp cdf_in.txt cdf.py
$ cat cdf_in.txt
10
5
3
2
1
$ rm cdf_in.txt
$ g++ -O3 -o cdf cdf.cpp
cdf.cpp: In function ‘int main(int, char**)’:
cdf.cpp:19: warning: deprecated conversion from string constant to ‘char*’
$ ./cdf in.txt
cdf_in.txt
$ ls cdf*
cdf cdf.cpp cdf.py
为什么 fout
不适用于 -O3
?
您的 strcat(res, o1);
取决于 res[0] == '[=13=]'
,这可能是正确的,但不能保证(res
是未初始化的本地,因此其内容不是 known/specified).
有可能在您不进行优化时将其初始化为零,但在您进行优化时则不会。
您可以通过初始化 res
或使用 strcpy
而不是 strcat
来修复您要复制到那里的第一个项目(但这仍然会留下可能的缓冲区溢出问题,所以请参阅下文以获得更好的选择)。
或者,当然,您可以编写更像 C++ 而不是 C 的代码,并使用 std::string
而不是 char 数组。
std::string fname("cdf_");
fname += argv[1];
std::ofstream fout(fname.c_str()); // just `fout(fname)` with a C++11 compiler
如果您出于某种原因真的想编写类似 C 的代码,在这种情况下使用 sprintf
可能更容易:
char res[30];
sprintf(res, "cdf_%35s", argv[1]);
std::ofstream fout(res);