简体   繁体   中英

std::ofstrean doesn't work with -O3

The following code, simply

1) takes an input file name from the command line argument, say in.txt

2) append the file name to "cdf_"

3) open a file with new name cdf_in.txt

4) simply read each line from (a number in each line) and send it to the output file.

#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;
}

By running the program without any optimization, it runs normally. However, by specifying -O3 , it fails to create the output file. Why???

$ 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

Why the fout doesn't work with -O3 ?

Your strcat(res, o1); depends on res[0] == '\\0' , which may be true, but isn't guaranteed ( res is an uninitialized local, so its contents aren't known/specified).

Chances are that it's being initialized to zeros when you don't do optimization, but not when you do.

You could fix it by initializing res , or by using strcpy instead of strcat for the first item you want to copy there (but this still leaves possible buffer overrun problems, so see below for better alternatives).

Or, of course, you could write code that's more like C++ instead of C, and use std::string instead of arrays of char.

std::string fname("cdf_");
fname += argv[1];

std::ofstream fout(fname.c_str()); // just `fout(fname)` with a C++11 compiler

If you really want to write C-like code for some reason, it's probably easier to use sprintf in this case:

char res[30];

sprintf(res, "cdf_%35s", argv[1]);

std::ofstream fout(res);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM