开发者

Avoiding memcpy in C++ buffered output

I am trying to write directly to an fstream output buffer to avoid a memcpy.

Why does the following code not work?

It compiles, runs and produces the right length output file on Linux. But the output file does not contain correct text. Also note that for some reas开发者_如何学Con, when I comment out the two lines involving str2, then an output file of zero length is produced.

Note: This example does not avoid memcpy, but if it works, it will help me avoid a memcpy in my application.

#include <fstream>

int main(int argc, char *argv[]) {
  std::fstream out;
  char buffer[512];
  out.rdbuf()->pubsetbuf(buffer, 512);
  out.open("file.txt", std::fstream::out);
  char *str1 = "test text.";
  strcpy(buffer, str1);
  out.rdbuf()->pubseekpos(strlen(str1), std::ios_base::out);
  char *str2 = "why?";
  out << str2;
  out.flush();
  out.close();
}


You give the stream a buffer for its internal use. Then you don't give it anything to write.

The fact that you copy something to the buffer without telling the stream doesn't give you anything in the file.

As you might have noticed, the seekpos is for positioning in the file, not for moving in the buffer. The buffer is for the stream's internal use only!


When you out.rdbuf()->pubseekpos(strlen(str1), std::ios_base::out);, this asks the stream to skip forwards through the newly created file. Can you expect it to take stuff from the buffer you specified? A clue: have you seen any examples involving specifying a buffer that said you needed to initialise it in some way or specify the initial number of non-garbage characters it contained? No... because the stream itself tracks which parts of the buffer are in use. Hence - when you take the presumed empty-buffer and skip forwards, it generates the intervening NULs. It wouldn't make sense for them to be set in the buffer (so simply doing a memcpy after the pubseekpos won't work either) - what if you've jumped more than a buffer-size forwards?

Hopefully this serves to at least illustrate the problem, although I haven't given any thought at this stage to how you might force the stream to change it's "tracking" of meaningful buffer content....


It's still early, but aren't you basically doing

#include <fstream>

int main(int argc, char *argv[]) 
{

  std::fstream out;
  out.open("file.txt", std::fstream::out);

  out << "test text";
  out << "why?";

  out.flush();
  out.close();
}

?


I'm not familiar enough with the C++ iostream library to say what is wrong with your program, I would only mention that if you want to do your own buffering it would likely be more straightforward to use the read() and write() interfaces directly (man 2 write). If you're doing your own buffering the iostream libraries probably won't buy you much, and will only obscure what's actually going on.


I see three possibilities

  1. Implement your own stream-buffer class
  2. Use the native file API
  3. Disable buffering with pubsetbuf(0, 0)

Implementing a stream-buffer is really not that difficult, and would give you the opportunity to mix C++ style stream insertion with direct memory access, without sacrificing performance.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜