Why does std::string_view::data not include a null terminator? - c++

This code has undefined behavior:
#include <string_view>
#include <iostream>
using namespace std::string_view_literals;
void foo(std::string_view msg) {
std::cout << msg.data() << '\n'; // undefined behavior if 'msg' is not null-
// terminated
// std::cout << msg << '\n'; is not undefined because operator<< uses
// iterators to print 'msg', but that's not the point
}
int main() {
foo("hello"sv); // not null-terminated - undefined behavior
foo("foo"); // same, even more dangerous
}
The reason why is that std::string_view can store non-null terminated strings, and doesn't include a null terminator when calling data. That's really limiting, as to make the above code defined behavior, I have to construct a std::string out of it:
std::string str{ msg };
std::cout << str.data() << '\n';
This really makes std::string_view unnecessary in this case, I still have to copy the string passed to foo, so why not use move semantics and change msg to a std::string? This might be faster, but I didn't measure.
Either way, having to construct a std::string every time I want to pass a const char* to a function which only accepts a const char* is a bit unnecessary, but there has to be a reason why the Committee decided it this way.
So, why does std::string_view::data not return a null-terminated string like std::string::data?

So, why does std::string_view::data not return a null-terminated
string like std::string::data
Simply because it can't. A string_view can be a narrower view into a larger string (a substring of a string). That means that the string viewed will not necessary have the null termination at the end of a particular view. You can't write the null terminator into the underlying string for obvious reasons and you can't create a copy of the string and return char * without a memory leak.
If you want a null terminating string, you would have to create a std::string copy out of it.
Let me show a good use of std::string_view:
auto tokenize(std::string_view str, Pred is_delim) -> std::vector<std::string_view>
Here the resulting vector contains tokens as views into the larger string.

The purpose of string_view is to be a range representing a contiguous sequence of characters. Limiting such a range to one that ends in a NUL-terminator limits the usefulness of the class.
That being said, it would still be useful to have an alternate version of string_view which is intended only to be created from strings that truly are NUL-terminated.
My zstring_view class is privately inherited from string_view, and it provides support for removing elements from the front and other operations that cannot make the string non-NUL-terminated. It provides the rest of the operations, but they return a string_view, not a zstring_view.
You'd be surprised how few operations you have to lose from string_view to make this work:
template<typename charT, typename traits = std::char_traits<charT>>
class basic_zstring_view : private basic_string_view<charT, traits>
{
public:
using base_view_type = basic_string_view<charT, traits>;
using base_view_type::traits_type;
using base_view_type::value_type;
using base_view_type::pointer;
using base_view_type::const_pointer;
using base_view_type::reference;
using base_view_type::const_reference;
using base_view_type::const_iterator;
using base_view_type::iterator;
using base_view_type::const_reverse_iterator;
using base_view_type::reverse_iterator;
using typename base_view_type::size_type;
using base_view_type::difference_type;
using base_view_type::npos;
basic_zstring_view(const charT* str) : base_view_type(str) {}
constexpr explicit basic_zstring_view(const charT* str, size_type len) : base_view_type(str, len) {}
constexpr explicit basic_zstring_view(const base_view_type &view) : base_view_type(view) {}
constexpr basic_zstring_view(const basic_zstring_view&) noexcept = default;
basic_zstring_view& operator=(const basic_zstring_view&) noexcept = default;
using base_view_type::begin;
using base_view_type::end;
using base_view_type::cbegin;
using base_view_type::cend;
using base_view_type::rbegin;
using base_view_type::rend;
using base_view_type::crbegin;
using base_view_type::crend;
using base_view_type::size;
using base_view_type::length;
using base_view_type::max_size;
using base_view_type::empty;
using base_view_type::operator[];
using base_view_type::at;
using base_view_type::front;
using base_view_type::back;
using base_view_type::data;
using base_view_type::remove_prefix;
//`using base_view_type::remove_suffix`; Intentionally not provided.
///Creates a `basic_string_view` that lacks the last few characters.
constexpr basic_string_view<charT, traits> view_suffix(size_type n) const
{
return basic_string_view<charT, traits>(data(), size() - n);
}
using base_view_type::swap;
template<class Allocator = std::allocator<charT> >
std::basic_string<charT, traits, Allocator> to_string(const Allocator& a = Allocator()) const
{
return std::basic_string<charT, traits, Allocator>(begin(), end(), a);
}
constexpr operator base_view_type() const {return base_view_type(data(), size());}
using base_view_type::to_string;
using base_view_type::copy;
using base_view_type::substr;
using base_view_type::operator==;
using base_view_type::operator!=;
using base_view_type::compare;
};

When dealing with string literals with known null terminators I usually use something like this to make sure the null is included in the counted chars.
template < size_t L > std::string_view string_viewz(const char (&t) [L])
{
return std::string_view(t, L);
}
The aim here is not to try to fix the compatibility issue, there are too many. But if you know what you are doing at want the string_view span to have a null ( Serialization ) then it is a nice trick.
auto view = string_viewz("Surrogate String");

Related

returning a std::string from a variant which can hold std::string or double

I have the following code:
#include <variant>
#include <string>
#include <iostream>
using Variant = std::variant<double, std::string>;
// helper type for the visitor
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
// explicit deduction guide (not needed as of C++20)
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
std::string string_from(const Variant& v)
{
return std::visit(overloaded {
[](const double arg) { return std::to_string(arg); },
[](const std::string& arg) { return arg; },
}, v);
}
int main()
{
Variant v1 {"Hello"};
Variant v2 {1.23};
std::cout << string_from(v1) << '\n';
std::cout << string_from(v2) << '\n';
return 0;
}
I have a function called string_from() which takes a variant and converts its inner value to a string.
The variant can hold either a std::string or a double.
In case of a std::string, I just return it.
In case of a double, I create a std::string from the double and then return it.
The problem is, I don't like the fact that I'm returning a copy of the std::string in case of a string-variant. Ideally, I would return a std::string_view or another kind of string observer.
However, I cannot return a std::string_view because in case of a double-variant I need to create a new temporary std::string and std::string_view is non-owning.
I cannot return a std::string& for the same reason.
I'm wondering if there's a way to optimize the code so that I can avoid the copy in case of a string-variant.
Note in my actual use case, I obtain strings from string-variants very frequently, but very rarely from double-variants.
But I still want to be able to obtain a std::string from a double-variant.
Also, in my actual use case, I usually just observe the string, so I don't really need the copy every time. std::string_view or some other string-observer would be perfect in this case, but it is impossible due to the reasons above.
I've considered several possible solutions, but I don't like any of them:
return a char* instead of a std::string and allocate the c-string somewhere on the heap in case of a double. In this case, I would also need to wrap the whole thing in a class which owns the heap-allocated strings to avoid memory leaks.
return a std::unique_ptr<std::string> with a custom deleter which would cleanup the heap-allocated strings, but would do nothing in case the string resides in the variant. Not sure how this custom deleter would be implemented.
Change the variant so it holds a std::shared_ptr<std::string> instead. Then when I need a string from the string-variant I just return a copy of the shared_ptr and when I need a string from the double-variant I call std::make_shared().
The third solution has an inherent problem: the std::string no longer resides in the variant, which means chasing pointers and losing performance.
Can you propose any other solutions to this problem? Something which performs better than copying a std::string every time I call the function.
You can return a proxy object. (this is like your unique_ptr method)
struct view_as_string{
view_as_string(const std::variant<double, std::string>& v){
auto s = std::get_if<std::string>(&v);
if(s) ref = s;
else temp = std::to_string(std::get<double>(v));
}
const std::string& data(){return ref?*ref:temp;}
const std::string* ref = nullptr;
std::string temp;
};
Use
int main()
{
std::variant<double, std::string> v1 {"Hello"};
std::variant<double, std::string> v2 {1.23};
std::cout << view_as_string(v1).data() << '\n';
view_as_string v2s(v2);
std::cout << v2s.data() << '\n';
}
The problem is, a variant holds different types, but you're trying to find a way to represent all of them in a single type. A string representation is useful for generic logging, but it has the downsides you describe.
For variants, I don't like trying to consolidate the values back into a single common thing, because if that was easily possible then there would be no need for the variant in the first place.
Better, I think, is to defer the conversion as late as possible, and keep forwarding it on to other functions that make use of the value as it is, or convert and forward until it's used--rather than trying to extract a single value and trying to use that.
A fairly generic function might look like this:
template <typename Variant, typename Handler>
auto with_string_view(Variant const & variant, Handler && handler) {
return std::visit(overloaded{
[&](auto const & obj) {
using std::to_string;
return handler(to_string(obj));
},
[&](std::string const & str) {return handler(str); },
[&](std::string_view str) { return handler(str); },
[&](char const * str) { return handler(str); }
}, variant);
}
Since the temporary created in the generic version outlives the call to the handler, this is safe and efficient. It also shows the "forward it on" technique that I've found to be very useful with variants (and visiting in general, even for non-variants.)
Also, I don't explicitly convert to string_view, but the function could add requirements that the handler accepts string views (if that helps document the usage.)
With the above helper function you might use it like this:
using V = std::variant<std::string, double>;
V v1{4.567};
V v2{"foo"};
auto print = [](std::string_view sv) { std::cout << sv << "\n";};
with_string_view(v1, print);
with_string_view(v2, print);
Here's a full live example, expanded out a little too: https://godbolt.org/z/n7KhEW7vY
If thread safety is not an issue, you could simply use a static std::string as the backing storage when returning a double value. Then you would be able to return a std::string_view, eg:
std::string_view string_from(const Variant& v)
{
static std::string buffer;
return std::visit(overloaded {
[&buffer](const double arg) -> std::string_view { buffer = std::to_string(arg); return buffer; },
[](const std::string& arg) -> std::string_view { return arg; },
}, v);
}
Online Demo
I've come up with my own solution inspired by apple apple's solution with the view_as_string class.
Here it is:
class owning_string_view : public std::string_view
{
public:
explicit owning_string_view(const char* str) : std::string_view{str}, m_string_buffer{} {}
explicit owning_string_view(const std::string& str) : std::string_view{str}, m_string_buffer{} {}
explicit owning_string_view(std::string&& str) : std::string_view{}, m_string_buffer{std::move(str)}
{
static_cast<std::string_view&>(*this) = m_string_buffer;
}
private:
std::string m_string_buffer;
};
Instead of taking a Variant I made it more generic and it takes strings instead.
For lvalue strings it just creates a std::string_view of the string.
For rvalue strings it moves the string into the buffer.
It extends from std::string_view so it can be used in std::string_view contexts seamlessly.
Of course you have to be careful not no slice off the std::string_view part from the object when creating an rvalue owning_string_view but this is true for std::string_view as well. You have to be careful not to take a std::string_view from an rvalue std::string.
Passing a owning_string_view as a std::string_view parameter to a function is safe for the same reason it is safe to pass an rvalue std::string as a std::string_view parameter to a function. The rvalue lives during the function call.
I also realized a deeper problem when returning a string_view from my Variantclass.
If I try to extract a std::string_view or a owning_string_view from an rvalue Variant I'm still going do end up with a dangling string_view, so I added 2 functions for taking a string from the Variant:
one accepts lvalue variants only and it returns owning_string_view.
the other accepts rvalue variants only and it returns a std::string, which is moved from the variant (since the variant is an rvalue).
One more observation: Ideally, I would make the first 2 constructors of owning_string_view constexpr but I can't because the default constructor of std::string is not constexpr. I hope this is changed in the future.

Can I get the raw pointer for a std::stringstream accumulated data with 0-copy?

Here is what I would like to do:
std::stringstream s;
s<<"Some "<<std::hex<<123<<" hex data"<<...;
Having this s, I would very much like to pass it around, and that is possible easily. However, at some point, there is a need to (conceptually) pass it to an interface that only accepts const void */size_t pair which describes the memory region.
As far as I see (would love to stand corrected), there is no way to do that with 0-copy in C++17 and below. One must use .str() which will create a string copy and then take it from there.
As a "hack", this is what I came up with:
struct stringstream_extractor_t {
// this structure will be used to get access to pbase member function which is protected
// the way we do that is to inherit from it
template <typename T>
struct accessor_t : public T {
static const char* data(const accessor_t* pT) { return pT->pbase(); }
};
// get the return type for std::stringstream::rdbuf
using bufferType = std::remove_pointer<decltype(((std::stringstream*)nullptr)->rdbuf())>::type;
// having the std::stringstream::rdbuf result type, we can now create our accessor type
// which will be able to call pbase inside it
using accessorType = accessor_t<bufferType>;
// this is where we deposit the data, in a const manner
const std::string_view _data;
// syntactic sugar: init the _data with the stuff from stream reference
stringstream_extractor_t(std::stringstream& stream) : _data{getBuffer(stream), static_cast<size_t>(stream.tellp())} {}
// syntactic sugar: init the _data with the stuff from stream pointer
stringstream_extractor_t(std::stringstream* pStream) :
_data{pStream ? getBuffer(*pStream) : nullptr, pStream ? static_cast<size_t>(pStream->tellp()) : 0} {}
// this uses the accessor type to grab access to data
static const char* getBuffer(const std::stringstream& stream) {
// we get the buffer and we cast it to our accessor type. This is safe, as we do not
// have any members inside it, just a static function
const accessorType* pBuffer = reinterpret_cast<accessorType*>(stream.rdbuf());
// grab the data now
return accessorType::data(pBuffer);
}
// convenience functionality
inline const char* data() const { return _data.data(); }
inline size_t size() const { return _data.size(); }
};
And here is how it is used, with a C-like interface
std::stringstream s;
s << "Hi there! " << std::hex << 0xdeadbeef;
const stringstream_extractor_t e(s);
write(2, e.data(), e.size());
Yes, I'm aware of the fact that the pointers must be kept alive (the std::stringstream instance), and all the life cycle implications.
Is there a more comfortable non-convoluted way to achieve this quite basic thing: get a buffer out from an output stringstream with move semantics.
I'm clearly missing something, this should not be this hard.
https://godbolt.org/z/G53P6oocb
Well in C++ 20 you could do this
#include <iostream>
#include <ios>
#include <sstream>
void c_style_func(const char* cp, std::size_t size) {
std::cout << std::string_view (cp,size) << "\n";
}
int main() {
std::stringstream s;
s << "Hi there! " << std::hex << 0xdeadbeef;
auto view = s.view();
c_style_func(view.data(), view.size());
}
using § 29.8.2.4 Page of the standard 1411
basic_string_view<charT, traits> view() const noexcept;
11 Let sv be basic_string_view<charT, traits>.
12 Returns: A sv object referring to the basic_stringbuf’s underlying character sequence in buf:
(12.1) — If ios_base::out is set in mode, then sv(pbase(), high_mark-pbase()) is returned.
(12.2) — Otherwise, if ios_base::in is set in mode, then sv(eback(), egptr()-eback()) is returned.
(12.3) — Otherwise, sv() is returned.
13 [Note: Using the returned sv object after destruction or invalidation of the character sequence underlying
*this is undefined behavior, unless sv.empty() is true. —end note]

C++ unordered_map<string, ...> lookup without constructing string

I have C++ code that investigates a BIG string and matches lots of substrings. As much as possible, I avoid constructing std::strings, by encoding substrings like this:
char* buffer, size_t bufferSize
At some point, however, I'd like to look up a substring in one of these:
std::unordered_map<std::string, Info> stringToInfo = {...
So, to do that, I go:
stringToInfo.find(std::string(buffer, bufferSize))
That constructs a std::string for the sole purpose of the lookup.
I feel like there's an optimization I could do here, by... changing the key-type of the unordered_map to some kind of temporary string imposter, a class like this...
class SubString
{
char* buffer;
size_t bufferSize;
// ...
};
... that does the same logic as std::string to hash and compare, but then doesn't deallocate its buffer when it's destroyed.
So, my question is: is there a way to get the standard classes to do this, or do I write this class myself?
What you're wanting to do is called heterogeneous lookup. Since C++14 it's been supported for std::map::find and std::set::find (note versions (3) and (4) of the functions, which are templated on the lookup value type). It's more complicated for unordered containers because they need to be told of or find hash functions for all key types that will produce the same hash value for the same text. There's a proposal under consideration for a future Standard: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0919r0.html
Meanwhile, you could use another library that already supports heterogenous lookup, e.g. boost::unordered_map::find.
If you want to stick to std::unordered_map, you could avoid creating so many string temporaries by storing a std::string member alongside your unordered_map that you can reassign values to, then pass that string to find. You could encapsulate this in a custom container class.
Another route is to write a custom class to use as your unordered container key:
struct CharPtrOrString
{
const char* p_;
std::string s_;
explicit CharPtrOrString(const char* p) : p_{p} { }
CharPtrOrString(std::string s) : p_{nullptr}, s_{std::move(s)} { }
bool operator==(const CharPtrOrString& x) const
{
return p_ ? x.p_ ? std::strcmp(p_, x.p_) == 0
: p_ == x.s_
: x.p_ ? s_ == x.p_
: s_ == x.s_;
}
struct Hash
{
size_t operator()(const CharPtrOrString& x) const
{
std::string_view sv{x.p_ ? x.p_ : x.s_.c_str()};
return std::hash<std::string_view>()(sv);
}
};
};
You can then construct CharPtrOrString from std::strings for use in the unordered container keys, but construct one cheaply from your const char* each time you call find. Note that operator== above has to work out which you did (convention used is that if the pointer's nullptr then the std::string member's in use) so it compares the in-use members. The hash function has to make sure a std::string with a particular textual value will produce the same hash as a const char* (which it doesn't by default with GCC 7.3 and/or Clang 6 - I work with both and remember one had an issue but not which).
In C++20, you can now do this:
// struct is from "https://www.cppstories.com/2021/heterogeneous-access-cpp20/"
struct string_hash {
using is_transparent = void;
[[nodiscard]] size_t operator()(const char *txt) const {
return std::hash<std::string_view>{}(txt);
}
[[nodiscard]] size_t operator()(std::string_view txt) const {
return std::hash<std::string_view>{}(txt);
}
[[nodiscard]] size_t operator()(const std::string &txt) const {
return std::hash<std::string>{}(txt);
}
};
// Declaration of map
std::unordered_map<std::string, Info, string_hash, std::equal_to<>> map;
std::string_view key = "foo";
if (map.find(key))
{
// do something here
}
Just note that you will still need std::string when using []. There may be a way around that, but I'm not too sure

Converting a char* returned by C API to C++ string

I found this code in a C++ header-only wrapper around a C API I'm working with:
static string GetString(const char* chString)
{
string strValue;
if (NULL != chString)
{
strValue.swap(string (chString));
releaseMemory((void*&)chString);
chString = NULL;
}
return strValue;
}
I suppose the author is trying to give the string strValue ownership of chString and then free the empty buffer. I suspect this is very wrong (including it being const char*), but it actually seems to work with MSVC 12. At least I haven't seen it crash spectacularly yet.
Assuming that the C API and the C++ library are using the same heap (so that the string can reallocate the buffer if necessary and eventually release it), is there a way to properly achieve this? How about this?
template <typename T> struct Deleter { void operator()(T o) { releaseMemory((void*&)o); } };
static std::string GetString(char* chString)
{
if (NULL == chString)
return std::string();
return std::string(std::unique_ptr<char[], Deleter<char[]>>(chString).get());
}
Again, assuming the C API is using the same heap as std::string.
If that's also very wrong, then is there an immutable, owning C-style string wrapper? Something like string_view but immutable (so const char* input would be ok) and owning (so it deletes the C string, possibly with a custom deleter, in its dtor)?
I suppose the author is trying to give the string strValue ownership of chString and then free the empty buffer.
No. It makes an (inefficient and error-prone) copy of the character data pointed to by chString, then releases the memory pointed to by chString (which will be skipped if the copy throws an exception), and then returns the copy.
Assuming that the C API and the C++ library are using the same heap
That is not a correct assumption, or even a necessary one. The copy can use whatever heap it wants.
is there a way to properly achieve this? How about this?
You are on the right track to use a std::unique_ptr with a custom deleter, but there is no reason to use the T[] array specialization of std::unique_ptr.
The code can be simplified to something more like this:
void Deleter(char* o) { releaseMemory((void*&)o); }
static std::string GetString(char* chString)
{
std::string strValue;
if (chString) {
std::unique_ptr<char, decltype(&Deleter)>(chString, &Deleter);
strValue = chString;
}
return strValue;
}
Or, just get rid of the check for chString being null, it is not actually needed. std::string can be constructed from a null char*, and std::unique_ptr will not call its deleter with a null pointer:
void Deleter(char* o) { releaseMemory((void*&)o); }
static std::string GetString(char* chString)
{
std::unique_ptr<char, decltype(&Deleter)>(chString, &Deleter);
return std::string(chString);
}
Does this seem like a good solution for my last question (and ultimate goal of being able to use a char* like a string without copying it)?
template <typename DeleterT = std::default_delete<const char*>>
class c_str_view
{
public:
unique_ptr<const char*, DeleterT> strPtr_;
size_t len_;
c_str_view() {}
c_str_view(const char* charPtr) : strPtr_(charPtr), len_(strlen(charPtr)) {}
c_str_view(const char* charPtr, size_t len) : strPtr_(charPtr), len_(len) {}
operator std::string_view () const
{
return string_view(strPtr_.get(), len_);
}
};
If so, is there a good reason this isn't in the upcoming standard since string_view is coming? It only makes sense with string_view of course, since any conversion to std::string would cause a copy and make the whole exercise pointless.
Here's a test:
http://coliru.stacked-crooked.com/a/9046eb22b10a1d87

Nullify QString data bytes

I use QStrings to store passwords. If to be more precise, I use QStrings to fetch passwords from GUI.
The point is that after password usage/appliance I need to nullify (zero) internal QStrings data bytes with password to eliminate it from memory entirely.
Here are my investigations:
After QString destruction it's data remains in memory nonzeroed;
When I attempt to modify QString to fulfill it with zeroes it triggers copy-on-write idiom and allocates new memory for a modified variant of data. Old data remains untouched. Same happens even if I use QString::data() method. Not really sure why - probably because it returns not raw char * but QChar *;
QString::clear(), = "" does actually the same COW as described above.
Q: How can I implement proper QString cleanup to prevent passwords leaks?
I've got two possible ways of bypassing copy-on-write. I've tried them and they seem to work - didn't use the Qt Creator's memory viewer, but the implicitly shared QStrings used in my code both pointed to the same zeroed data afterwards.
Using constData()
As written in the Qt docs for QString::data() method:
For read-only access, constData() is faster because it never causes a
deep copy to occur.
So the possible solution looks like this:
QString str = "password";
QString str2 = str;
QChar* chars = const_cast<QChar*>(str.constData());
for (int i = 0; i < str.length(); ++i)
chars[i] = '0';
// str and str2 are now both zeroed
This is a legitimate use of const_cast since the underlying data is not really const, so no undefined behaviour here.
Using iterators
From the Qt docs for implicit sharing:
An implicitly shared class has control of its internal data. In any
member functions that modify its data, it automatically detaches
before modifying the data. Notice, however, the special case with
container iterators; see Implicit sharing iterator problem.
So let's move to the section describing this iterator problem:
Implicit sharing has another consequence on STL-style iterators: you
should avoid copying a container while iterators are active on that
container. The iterators point to an internal structure, and if you
copy a container you should be very careful with your iterators. E.g.:
QVector<int> a, b;
a.resize(100000); // make a big vector filled with 0.
QVector<int>::iterator i = a.begin();
// WRONG way of using the iterator i:
b = a;
/*
Now we should be careful with iterator i since it will point to shared data
If we do *i = 4 then we would change the shared instance (both vectors)
The behavior differs from STL containers. Avoid doing such things in Qt.
*/
a[0] = 5;
/*
Container a is now detached from the shared data,
and even though i was an iterator from the container a, it now works as an iterator in b.
*/
It is my understanding that, based on the above docs fragment, you should be able to exploit this "wrong usage" of iterators to manipulate your original string with iterators as they don't trigger copy-on-write. It's important that you "intercept" the begin() and end() before any copying occurs:
QString str = "password";
QString::iterator itr = str.begin();
QString::iterator nd = str.end();
QString str2 = str;
while (itr != nd)
{
*itr = '0';
++itr;
} // str and str2 still point to the same data and are both zeroed
You have to be aware of all the temporary copies that may be done. If you want to avoid this you must manually erase memory before deallocating each temporal copy. Unfortunately that cannot be done with the standard QString since the implementation is closed.
You can, however, specialise std::basic_string using a custom allocator, which, before deleting can clean up the memory block (see below for an example). You can use this new secure string to manipulate your password instead of a plain char array, if you find it more convenient. I'm not sure is std::basic_string can be specialised with QChar, but if not you can use any of the Unicode characters from C++11 (char16_t, char32_t...) instead if you need other than ANSI support.
Regarding the user interface, I think an option you have is to create your own text input widget, reimplementing the keyPressEvent / keyReleaseEvent to store the typed password into either the secure string or a char array. Also reimplement the paintEvent to display only stars, dots, or whatever other masking character you want. Once the password has been used just clear the array or empty the secure string.
Update: example of secure string
namespace secure {
template<class T>
class allocator : public std::allocator<T> {
public:
typedef typename std::allocator<T>::pointer pointer;
typedef typename std::allocator<T>::size_type size_type;
template<class U>
struct rebind {
typedef allocator<U> other;
};
allocator() throw() :
std::allocator<T>() {}
allocator(const allocator& other) throw() :
std::allocator<T>(other) {}
template <class U>
allocator(const allocator<U>& other) throw() :
std::allocator<T>(other) {}
void deallocate(pointer p, size_type num) {
memset(p, 0, num); // can be replaced by SecureZeroMemory(p, num) on Windows
std::allocator<T>::deallocate(p, num);
}
};
class string : public std::basic_string<char, std::char_traits<char>, allocator<char>> {
public:
string() :
basic_string() {}
string(const string& str) :
basic_string(str.data(), str.length()) {}
template<class _Elem, class _Traits, class _Ax>
string(const std::basic_string<_Elem, _Traits, _Ax>& str) :
basic_string(str.begin(), str.end()) {}
string(const char* chars) :
basic_string(chars) {}
string(const char* chars, size_type sz) :
basic_string(chars, sz) {}
template<class _It>
string(_It a, _It b) :
basic_string(a, b) {}
};
}