Reputation: 8315
I am writing a string class (Utf8String) that wraps (has) a std::string (because it's handy).
For some reason I have to access the internal buffer of the wrapped std::string to write directly into it. I know this is dirty and against encapsulation principles and all that, but I have to do it.
Let the following Utf8String class members :
std::basic_string< char > m_sBuf;
inline char * Reserve( uint32_t nNewByteCap )
{
m_sBuf.reserve( nNewByteCap );
return const_cast< char * >( m_sBuf.c_str() );
}
inline void Resize( uint32_t nNewByteCount )
{
// Some stuff ...
m_sBuf.resize( nNewByteCount, ' ' );
}
In order to do something like this :
Utf8String sMessage;
char * sBuffer = sMessage.Reserve( 1024 );
uint32_t nRealLen = some_c_function_write_to_buffer( sBuffer, sMessage.Capacity() );
sMessage.Resize( nRealLen );
I am not certain how the STL works internally. As far as i know, it accepts having null characters lost in the middle of a std::string, so placing a null character before the actual end of the string should not be a problem.
Since STL implementations can be different on different platforms, testing on mine won't mean that it works on other platforms too.
Do you see something in this piece of code that can break the std::string object i'm using ? Thanks for your help.
PS : I can't use C++11.
Upvotes: 2
Views: 570
Reputation: 27365
From http://en.cppreference.com/w/cpp/string/basic_string/c_str:
Writing to the character array accessed through c_str() is undefined behavior. You shouldn't do that.
Safer code:
Utf8String sMessage;
std::array<char, 1024> buffer;
uint32_t nRealLen = some_c_function_write_to_buffer( buffer.data(), buffer.size() );
sMessage.Assign(sBuffer.begin(), sBuffer.end());
The last line assumes you have in your string class:
template<typename InIt>
void Assign(InIt begin, InIt end) {
m_sBuf.assign(begin, end);
}
(or equivalent).
This is better because it doesn't use access to the data returned by c_str and it doesn't attempt to manage the memory in std::string manually.
Upvotes: 2