I was going through these two class implementations and found out that the strstream class is deprecated.
And if I use the stringstream class as replacement, then there is big difference between how they log in the buffer since the stringstream class object maintains a deep copy of the buffer.
Has anyone faced any problem while replacing strstream with stringstream class?
What would be the output of this code and why?
#include<iostream>
#include <sstream>
#include <strstream>
int main(){
char strArr[] = "Soheb Khan is great";
char stringArr[] = "TurboCharging";
std::strstream strStream(strArr,19);
std::stringstream stringStream(std::string(stringArr,19));
std::cout<<"Before Modification strArr= "<<strArr<<" & stringArr= "<<stringArr<<std::endl;
strStream << "Fifa 2012 is nice";
stringStream << "Sometimes its sucks";
std::cout<<"After Modification strArr= "<<strArr<<" & stringArr= "<<stringArr<<std::endl;
return 0;
}
The classes from <strstream> are hideous to use. When they were more popular I haven't seen any correct production used (well, they got corrected when I spotted the problems). Either people didn't terminate the string using std::ends or they didn't release the memory using s.freeze(0) (or, most often, both). Although the <sstream> class do create a copy I haven't found this to be a problem.
In case memory allocation actually matters for your use case, either because you need to allocate large chunks or because you have many of them, you can take control easily and have data read from or written to buffers you provide using a custom stream buffer. For example, a stream buffer writing to a readily allocate chunk of memory is trivial to write:
struct omembuf
: std::streambuf {
{
omembuf(char* base, std::size_t size) {
this->setp(base, base + size);
}
char* begin() const { return this->pbase(); }
char* end() const { return this->pptr(); }
};
Related
Say I am given a long and null-terminated cstring as char* text_ptr. I own text_ptr and I am responsible of free()ing it. Currently, I use text_ptr and free() it each time after use.
I try to improve memory safety a bit by wrapping it in a C++ class so that I can enjoy the benefit of RAII. There could be many ways to achieve it. A naive way is: string text_ptr(text_ptr);. However, by doing so, memory is copied once and I still need to manually free() my text_ptr. It would be better if I can avoid memory copy and free() (as this text_ptr is created frequently, performance could take a big hit if I copy it each time). My current thought:
Is it possible to transfer the ownership of text_ptr to a string text_str? Hypothetically, I do text_str.data() = text_ptr;.
Thanks
std::string can't receive ownership of an external buffer. The best you can do is std::unique_ptr.
By default std::unique_ptr will use delete (or delete[]), but you need std::free(), so a custom deleter is required:
#include <cstdlib>
#include <memory>
struct FreeDeleter
{
void operator()(void *p) const
{
std::free(p);
}
};
int main()
{
std::unique_ptr<char[], FreeDeleter> ptr((char *)malloc(42));
}
If you also store the length, you can construct a temporary std::string_view from pointer+length when needed, to conveniently read the string.
Or, a oneliner: std::unique_ptr<char[], std::integral_constant<void(*)(void *), std::free>>.
Another one for C++20: std::unique_ptr<char[], decltype([](void *p){std::free(p);})>.
An idea (not sure it’s a good one, tho)
#include <iostream>
#include <string_view>
#include <cstring>
#include <memory>
struct my_string_view : public std::string_view
{
using std::string_view::string_view;
std::shared_ptr<char[]> _data;
explicit my_string_view( char * data )
: std::string_view(data)
, _data{data, free}
{ }
};
void f( const my_string_view & s )
{
std::cout << "f: \"" << s << "\"\n";
}
int main()
{
my_string_view s( strdup( "Hello world!" ) );
f( s );
std::cout << "main: \"" << s << "\"\n";
}
(This version requires C++17. For older versions of the standard you’ll have to specify the default_deleter<char[]>() explicitly.)
I'm having a data abort exception in my code. It is very likely I am doing a very bad operation with chars. This code seems to work, but I wonder if it is actually invalid. The question is, what happens if you copy the data of one struct to another with char arrays involved. How is the data copied?
I have two functions, one which will purposefully leak, because I want to also know what happens if the struct created with new lives on purposefully, but the struct whose data it copied goes out of scope.
// Example program
#include <iostream>
#include <string>
#include "string.h"
typedef struct {
char name[12];
char stupid[12];
int hello;
} tFile;
void CopyFileAndDelete(tFile *file1){
tFile *file2 = new tFile;
*file2 = *file1;
std::cout << file2->name << std::endl;
delete file2;
}
void CopyFileAndLeak(tFile *file1){
tFile *file2 = new tFile;
*file2 = *file1;
std::cout << file2->name << std::endl;
}
int main()
{
tFile file1;
memset(&file1, 0, sizeof file1);
file1.hello = 22;
snprintf(file1.name, 12, "%s", "hellogoodfriendhwoareyou");
snprintf(file1.stupid, 12, "%s", "greate");
CopyFileAndDelete(&file1);
CopyFileAndLeak(&file1);
}
Other than this code being generally unsafe and more C than C++, it's correct (other than the leak.) There is no way this can produce an exception (unless new throws due to memory allocation failure.)
Arrays inside structs will be copied as you'd expect. The compiler will generally do a memcpy() to copy them (or a special memcpy-like built-in to optimize the copy operation.)
This isn't code you should write though. Use std::string instead. Don't use new and delete, use value types instead. If you really need to allocate, use unique_ptr or shared_ptr to do it.
Don't write code like this in C++ :-)
Introduction
I'm writing some communication application. Before C++17 (without Boost), I use std::string and its const reference as cls1.
Since C++17, I introduced std::string_view to my code as cls2.
However, I don't have clear policy when should I use std::string_view. My communication application receives data from the network and it is stored to recv_buffer. And creates some application classes from recv_buffer.
Construction
If I focus only cls1's constructor, move construction is efficient. But I think that where the parameter s from. If it is originally from the recv_buffer, I can create std::string_view at the receiving (very early) point. And during recv_buffer's lifetime is enabled, use std::string_view everywhere. If I need to store the part of recv_buffer then create std::string.
An only exception I noticed is the recv_buffer is always contained complete data for my application class. In this case, move construction is efficient.
Getter
I think using the return type as std::string_view has advantage. Some member function such as substr() is efficient. But I don't see any disadvantage, so far.
Question
I suspect that I might see only pros of std::string_view. Before re-writing many codes, I would like to know your ideas.
PoC code
#include <string>
struct cls1 {
explicit cls1(std::string s):s_(std::move(s)) {}
std::string const& get() const { return s_; }
private:
std::string s_;
};
struct cls2 {
explicit cls2(std::string_view s):s_(s) {}
std::string_view get() const { return s_; }
private:
std::string s_;
};
#include <iostream>
int main() {
// If all of the receive buffer is the target
{
std::string recv_buffer = "ABC";
cls1 c1(std::move(recv_buffer)); // move construct
std::cout << c1.get().substr(1, 2) << std::endl; // create new string
}
{
std::string recv_buffer = "ABC";
cls2 c2(recv_buffer); // copy happend
std::cout << c2.get().substr(1, 2) << std::endl; // doesn't create new string
}
// If a part of the receive buffer is the target
{
std::string recv_buffer = "<<<ABC>>>";
cls1 c1(recv_buffer.substr(3, 3)); // copy happend and move construct
std::cout << c1.get().substr(1, 2) << std::endl; // create new string
}
{
std::string recv_buffer = "<<<ABC>>>";
std::string_view ref = recv_buffer;
cls2 c2(ref.substr(3, 3)); // string create from the part of buffer directly
std::cout << c2.get().substr(1, 2) << std::endl; // doesn't create new string
}
}
Running Demo: https://wandbox.org/permlink/TW8w3je3q3D46cjk
std::string_view is a way to get some std::string const member functions without creating a std::string if you have some char* or you want to reference subset of a string.
Consider it as a const reference. If the object it refers vanishes (or changes) for any reason, you have a problem. If your code can return a reference, you can return a string_view.
Example:
#include <cstdio>
#include <string>
#include <vector>
#include <string.h>
#include <iostream>
int main()
{
char* a = new char[10];
strcpy(a,"Hello");
std::string_view s(a);
std::cout << s; // OK
delete[] a;
std::cout << s; // whops. UD. If it was std::string, no problem, it would have been a copy
}
More info.
Edit: It doesn't have a c_str() member because this needs the creation of a \0 at the end of the substring which cannot be done without modification.
Don't return a string view when:
The caller needs a null terminated string. This is often the case when dealing with C API's.
You don't store the string itself somewhere. You do store the string in a member in this case.
Do realise, that the string view becomes invalidated by operations on the original string such as changing the capacity, as well as if the original string is destroyed. If the caller needs the string for a longer than the life time of the object that stores the string, then they can copy from the view into their own storage.
I'd like an interface for writing to an automatically resizing array. One way to do this is with a generic std::ostream *.
Then consider if ostringstream is the target:
void WritePNG(ostream *out, const uint8_t *pixels);
void *WritePNGToMemory(uint8_t *pixels)
{
ostringstream out;
WritePng(&out, pixels);
uint8_t *copy = new uint8_t[out.tellp()];
memcpy(copy, out.str().c_str(), out.tellp()];
return copy;
}
But I want to avoid the memcpy(). Is there a way to take ownership of the array in the underlying stringbuf class and return that?
I get the feeling this can't be done using standard library, since the stream buffer might not even be a contiguous array.
If you're willing to use the old, deprecated <strstream> interface, this is fairly easy - just create a std::strstreambuf pointing at your storage, and it will work by magic. std::ostrstream even has a constructor to do this for you:
#include <iostream>
#include <strstream>
int main()
{
char copy[32] = "";
std::ostrstream(copy, sizeof copy) << "Hello, world!"
<< std::ends << std::flush;
std::cout << copy << '\n';
}
With the more modern <sstream> interface, you need to access the string stream's buffer, and call pubsetbuf() to make it to point at your storage:
#include <iostream>
#include <sstream>
int main()
{
char copy[32] = "";
{
std::ostringstream out{};
out.rdbuf()->pubsetbuf(copy, sizeof copy);
out << "Hello, world!" << std::ends << std::flush;
}
std::cout << copy << '\n';
}
Obviously, in both cases, you'll need a way to know in advance how much memory to allocate for copy, because you can't wait until tellp() is ready for you...
Here's the solution I ended up using. The idea is the same as the one proposed by HostileFork - only needing to implement overflow(). But as already hinted, it has much better throughput by buffering. It also optionally supports random access (seekp(), tellp()).
class MemoryOutputStreamBuffer : public streambuf
{
public:
MemoryOutputStreamBuffer(vector<uint8_t> &b) : buffer(b)
{
}
int_type overflow(int_type c)
{
size_t size = this->size(); // can be > oldCapacity due to seeking past end
size_t oldCapacity = buffer.size();
size_t newCapacity = max(oldCapacity + 100, size * 2);
buffer.resize(newCapacity);
char *b = (char *)&buffer[0];
setp(b, &b[newCapacity]);
pbump(size);
if (c != EOF)
{
buffer[size] = c;
pbump(1);
}
return c;
}
#ifdef ALLOW_MEM_OUT_STREAM_RANDOM_ACCESS
streampos MemoryOutputStreamBuffer::seekpos(streampos pos,
ios_base::openmode which)
{
setp(pbase(), epptr());
pbump(pos);
// GCC's streambuf doesn't allow put pointer to go out of bounds or else xsputn() will have integer overflow
// Microsoft's does allow out of bounds, so manually calling overflow() isn't needed
if (pptr() > epptr())
overflow(EOF);
return pos;
}
// redundant, but necessary for tellp() to work
// https://stackoverflow.com/questions/29132458/why-does-the-standard-have-both-seekpos-and-seekoff
streampos MemoryOutputStreamBuffer::seekoff(streamoff offset,
ios_base::seekdir way,
ios_base::openmode which)
{
streampos pos;
switch (way)
{
case ios_base::beg:
pos = offset;
break;
case ios_base::cur:
pos = (pptr() - pbase()) + offset;
break;
case ios_base::end:
pos = (epptr() - pbase()) + offset;
break;
}
return seekpos(pos, which);
}
#endif
size_t size()
{
return pptr() - pbase();
}
private:
std::vector<uint8_t> &buffer;
};
They say a good programmer is a lazy one, so here's an alternate implementation I came up with that needs even less custom code. However, there's a risk for memory leaks because it hijacks the buffer inside MyStringBuffer, but doesn't free MyStringBuffer. In practice, it doesn't leak for GCC's streambuf, which I confirmed using AddressSanitizer.
class MyStringBuffer : public stringbuf
{
public:
uint8_t &operator[](size_t index)
{
uint8_t *b = (uint8_t *)pbase();
return b[index];
}
size_t size()
{
return pptr() - pbase();
}
};
// caller is responsible for freeing out
void Test(uint8_t *&_out, size_t &size)
{
uint8_t dummy[sizeof(MyStringBuffer)];
new (dummy) MyStringBuffer; // construct MyStringBuffer using existing memory
MyStringBuffer &buf = *(MyStringBuffer *)dummy;
ostream out(&buf);
out << "hello world";
_out = &buf[0];
size = buf.size();
}
IIRC the whole reason stringstream exists (vs strstream) was to sort out the fuzzy questions of memory ownership that would come up by giving direct buffer access. e.g. I think that change was to specifically prevent what you are asking to do.
One way or another I think you'd have to do it yourself, by overriding the stream buffer. To answer a similar question I suggested something for input streams that wound up getting quite a few upvotes. But honestly I didn't know what I was talking about then, nor now when I suggest the following:
Hacking up this link from the web for doing an "uppercasing stream buffer" to one that just echoes and gives you a reference to its buffer might give:
#include <iostream>
#include <streambuf>
class outbuf : public std::streambuf {
std::string data;
protected:
virtual int_type overflow (int_type c) {
if (c != EOF)
data.push_back(c);
return c;
}
public:
std::string& get_contents() { return data; }
};
int main() {
outbuf ob;
std::ostream out(&ob);
out << "some stuff";
std::string& data = ob.get_contents();
std::cout << data;
return 0;
}
I'm sure it's broken in all kinds of ways. But the uppercase-buffer-authors seemed to think that overriding the overflow() method alone would let them uppercase all output to the stream, so I guess one could argue that it's enough to see all output if writing to one's own buffer.
But even so, going one character at a time seems suboptimal...and who knows what overhead you get from inheriting from streambuf in the first place. Consult your nearest C++ iostream expert for what the actual right way is. But hopefully it's proof that something of the sort is possible.
The following program prints 0.
#include <ostream>
#include <string>
#include <sstream>
#include <iostream>
int main()
{
std::string subjectString("subject");
std::ostream tempStream(NULL);
tempStream << subjectString;
std::ostream& updatedStream = tempStream;
std::stringstream ss;
ss << updatedStream;
std::cout << ss.str() << std::endl;
return 0;
}
Why?
EDIT
As per Niall's sugesstion, I tried:
#include <ostream>
#include <string>
#include <sstream>
#include <iostream>
int main()
{
std::string subjectString("subject");
std::stringbuf buffer;
std::ostream tempStream(&buffer);
buffer.sputn(subjectString.c_str(), subjectString.size());
std::stringstream ss;
ss << tempStream;
std::cout << ss.str() << std::endl;
return 0;
}
Even this prints an address. Not the actual string.
The construction of std::ostream requires a buffer (not NULL).
In addition, basic_stream objects are not copyable;
basic_ostream( const basic_ostream& rhs ) = delete;
Reference;
http://en.cppreference.com/w/cpp/io/basic_ostream/basic_ostream
Try something more like this;
// ...
std::stringbuf buffer;
std::ostream tempStream(&buffer);
// ...
To associate a buffer with the stream.
Following on some of the discussions and edits;
In general, I would not directly manipulate the buffer, you should rather use the stream instead tempStream.write(...). The exact details are beyond the immediate question/problem; being the initialisation of the first stream with the buffer and streaming content into that stream. If all you want to do with the code is check if the data is in the buffer, then you could use tempStream.rdbuf()->sgetn(...).
You have already mentioned that this is part of a larger problem.
In the context of some the comments here and the original problem; this could be a case in which direct manipulation of the buffer is needed (in much the same way as the stream would). Your implementation would need to be well tested since this is not "the usual" way of working with streams, but it can work; .rdbuf() is the manner in which you can get to the underlying buffer. I don't have an exact snippet (maybe that's another question), but you can "clear the buffer" by resetting the position(s) of the put and get areas to be the same (see the positioning, put and get area functions of the buffer - std::ostream::seekp was mentioned as being used to deal with this). I think you standard library implementation of stringstream could also offer some useful hints.
Because tempStream has no stream to hold anything.
ss.str() returns NULL (0).