Passing std::vector’s Underlying Array to C APIs

Often, there’s a need to pass some data stored as an array from C++ to C-interface APIs. The “default” first-choice STL container for storing arrays in C++ is std::vector. So, how to pass the array content managed by std::vector to a C-interface API?

The Wrong Way I saw that kind of C++ code:

// v is a std::vector<BYTE>.
// Pass it to a C-interface API: pointer + size in bytes
DoSomethingC( 
  /* Some cast, e.g.: (BYTE*) */ &v, 
  sizeof(v) 
);

That’s wrong, in two ways: for both the pointer and the size. Let’s talk the size first: sizeof(v) represents the size, in bytes, of an instance of std::vector, which is in general different from the size in bytes of the array data managed by the vector. For example, suppose that a std::vector is implemented using three pointers, e.g. to begin of data, to end of data, and to end of reserved capacity; in this case, sizeof(v) would be sizeof(pointer) * 3, which is 8 (pointer size, in bytes, in 64-bit architectures) * 3 = 24 bytes on 64-bit architectures (4*3 = 12 bytes on 32-bit).

But what the author of that piece of code actually wanted was the size in bytes of the array data managed (pointed to) by the std::vector, which you can get multiplying the vector’s element count returned from v.size() by the size in bytes of a single vector element. For a vector<BYTE>, the value returned by v.size() is just fine (in fact, sizeof(BYTE) is one).

Now let’s discuss the address (pointer) problem. “&v” points to the beginning of the std::vector’s internal representation (i.e. the internal “guts” of std::vector), which is implementation-defined, and isn’t interesting at all for the purpose of that piece of code. Actually, misinterpreting the std::vector’s internal implementation details with the array data managed by the vector is dangerous, as in case of write access the called function will end up stomping the vector’s internal state with unrelated bytes. So, on return, the vector object will be in a corrupted and unusable state, and the memory previously owned by the vector will be leaked.

In case of read access, the vector’s internal state will be read, instead of the intended actual std::vector’s array content.

The presence of a cast is also a signal that something may be wrong in the user’s code, and maybe the C++ compiler was actually helping with a warning or an error message, but it was silenced instead.

So, how to fix that? Well, the pointer to the array data managed by std::vector can be retrieved calling the vector::data() method. This method is offered in both a const version for read-only access to the vector’s content, and in a non-const version, for read-write access.

The Correct Way So, the correct code to pass the std::vector’s underlying array data to a C-interface API expecting a pointer and a size would be for the case discussed above:

DoSomethingC(v.data(), v.size());

Or, if you have e.g. a std::vector<double> and the size parameter is expressed in bytes (instead of element count):

DoSomethingC(v.data(), v.size() * sizeof(double));

An alternative syntax to calling vector::data() would be “&v[0]”, although the intent using vector::data() seems clearer to me. Moreover, vector::data() works also for empty vectors, returning nullptr in this case. Instead, “&v[0]” triggers a “vector subscript out of range” debug assertion failure in MSVC when used on an empty vector (in fact, for an empty vector it doesn’t make sense to access the first item at index zero, as the vector is empty and there’s no first item).

&v[0] on an empty vector: debug assertion failure
&v[0] on an empty vector: debug assertion failure

What’s Wrong with My UTF-8 Strings in Visual Studio?

Probably nothing: Maybe you just have to tell Visual Studio it’s an UTF-8-encoded string!

The std::string class can be used to store UTF-8-encoded Unicode text.

For example:

std::string s{"LATIN SMALL LETTER E WITH GRAVE (U+00E8): \xC3\xA8"};

However, in the Locals window, instead of the expected è (Latin small letter e with grave, U+00E8), Visual Studio displays some (apparently) garbage characters, like a Latin capital letter A with tilde, followed by diaeresis.

UTF-8 String Misinterpreted in the Locals Window
UTF-8 String Misinterpreted in the Locals Window

Why is that? Is there a bug in our C++ code? Did we pick the wrong UTF-8 bytes for ‘è’?

No. The UTF-8 encoding for è (U+00E8) is exactly the 2-byte sequence 0xC3 0xA8, so the above C++ code is correct.

The problem is that Visual Studio doesn’t use the UTF-8 encoding to display that string in the Locals window. It turns out that VS is probably using the Windows-1252 code page (a character encoding commonly mislabeled as “ANSI” on Windows…). And, in this character encoding, the first byte 0xC3 is mapped to à (U+00C3: Latin capital letter A with tilde), and the second byte 0xA8 is mapped to ¨ diaeresis (U+00A8).

To display the string content using the correct UTF-8 encoding, you can use the explicit “s8” format specifier. For example, typing in the Command Window:

? &s[0],s8

the correct string is displayed, as this time the bytes in the std::string variable are interpreted as a UTF-8 sequence.

 

The s8 Format Specifier in the Command Window
The s8 Format Specifier in the Command Window

 

Similarly, the s8 format specifier can be used in the Watch window as well.

The s8 Format Specifier in the Watch Window
The s8 Format Specifier in the Watch Window

 

How Small Is Small Enough for the SSO?

Yesterday I wrote about the SSO.

A good question would be: “What is the maximum length threshold to trigger the SSO?” In other words: How long is too much for a string to enable the SSO?

Well, this limit length is not specified by the standard. However, for the sake of curiosity, in VS2015’s implementation, the limit is 15 for “narrow (i.e. char-based) strings, and 7 for “wide (i.e. wchar_t-based) strings.

This means that “meow”, “Connie” and “Commodore” are valid candidates for the SSO, as their lengths are less than 16 chars. On the other hand, considering the corresponding wide strings, L“meow” and L“Connie” are still SSO’ed, as their lengths are less than 8 wchar_ts; however, L“Commodore” breaks the 7 wide characters limit, so it’s not SSO’ed.

Thanks to Mr. STL for his clarification on the SSO length limit in Visual Studio’s implementation.

 

The Small String Optimization

How do “Connie” and “meow” differ from “The Commodore 64 is a great computer”?

(Don’t get me wrong: They are all great strings! 🙂 )

In several implementations, including the Visual C++’s one, the STL string classes are empowered by an interesting optimization: The Small String Optimization (SSO).

What does that mean?

Well, it basically means that small strings get a special treatment. In other words, there’s a difference in how strings like “Connie”, “meow” or “The Commodore 64 is a great computer” are allocated and stored by std::string.

In general, a typical string class allocates the storage for the string’s text dynamically from the heap, using new[]. In Visual Studio’s C/C++ run-time implementation on Windows, new[] calls malloc, which calls HeapAlloc (…which may probably call VirtualAlloc). The bottom line is that dynamically-allocating memory with new[] is a non-trivial task, that does have an overhead, and implies a trip down the Windows memory manager.

So, the std::string class says: “OK, for small strings, instead of taking a trip down the new[]-malloc-HeapAlloc-etc. “memory lane” 🙂 , let’s do something much faster and cooler! I, the std::string class, will reserve a small chunk of memory, a “small buffer” embedded inside std::string objects, and when strings are small enough, they will be kept (deep-copied) in that buffer, without triggering dynamic memory allocations.”

That’s a big saving! For example, for something like:

std::string s{"Connie"};

there’s no memory allocated on the heap! “Connie” is just stack-allocated. No new[], no malloc, no HeapAlloc, no trip down the Windows memory manager.

That’s kind of the equivalent of this C-ish code:

char buffer[ /* some short length */ ];
strcpy_s(buffer, "Connie");

No new[], no HeapAlloc, no virtual memory manager overhead! It’s just a simple snappy stack allocation, followed by a string copy.

But there’s more! In fact, having the string’s text embedded inside the std::string object offers great locality, better than chasing pointers to scattered memory blocks allocated on the heap. This is also very good when strings are stored in a std::vector, as small strings are basically stored in contiguous memory locations, and modern CPUs love blasting contiguous data in memory!

Optimizations similar to the SSO can be applied also to other data structures, for example: to vectors. This year’s CppCon had an interesting session discussing that: “High Performance Code 201: Hybrid Data Structures”.

I’ve prepared some C++ code implementing a simple benchmark to measure the effects of SSO. The results I got for 200,000-small-string vectors clearly show a significant advantage of STL strings for small strings. For example: in 64-bit build on an Intel i7 CPU @3.40GHz: vector::push_back time for ATL (CStringW) is 29 ms, while for STL (wstring) it’s just 14 ms: one half! Moreover, sorting times are 135 ms for ATL vs. 77 ms for the STL: again, a big win for the SSO implemented in the STL!

 

Printing Non-ASCII Characters to the Console on Windows

…A subtitle could read as: “From Greek letters to Os”.

I came across some Windows C++ source code that printed the Greek small letter pi (π, U+03C0) and capital letter sigma (Σ, U+03A3) to the console, as part of some mathematical formulae. A minimal reproducible code snippet based on the original code looks like this:

#include <stdio.h>

#define CHAR_SIGMA 227
#define CHAR_PI 228

int main()
{
    printf("Greek pi: %c\n", CHAR_PI);
    printf("Greek Sigma: %c\n", CHAR_SIGMA);
}

When executed on the original author’s PC, the above code prints the expected Greek letters correctly. However, when I run the exact same code on my PC, I got this wrong output:

Greek letters wrongly printed to the console
Greek letters wrongly printed to the console

What’s going wrong here?

The problem is that the author of that code probably looked up the codes for those Greek letters in some code page, probably code page 437.

However, on my Windows PC, the default code page for the console seems to be a different one, i.e. code page 850; in fact, in this code page (850) the codes 227 and 228 are mapped to Ò and õ (instead of Σ and π) respectively.

How to fix that?

I would suggest using Unicode instead of code pages. On Windows, the default “native” Unicode encoding is UTF-16. Using UTF-16, π (U+03C0) is encoded as the 16-bit code unit 0x03C0 ; Σ (U+03A3) is encoded as 0x03A3.

This code snippet shows UTF-16 console output in action:

#include <fcntl.h>
#include <io.h>
#include <stdio.h>

int wmain( /* int argc, wchar_t* argv[] */ )
{
    // Enable Unicode UTF-16 output to console
    _setmode(_fileno(stdout), _O_U16TEXT);

    // Use UTF-16 encoding for Greek letters
    static const wchar_t kPi = 0x03C0;
    static const wchar_t kSigma = 0x03A3;
    
    wprintf(L"Greek pi: %c\n", kPi);
    wprintf(L"Greek Sigma: %c\n", kSigma);
}
Greek letters correctly printed to the console
Greek letters correctly printed to the console

Note the use of _setmode and _O_U16TEXT to enable UTF-16 output to the console, and the associated <fcntl.h> and <io.h> additional headers. (More details on those can be found in this blog post.)

P.S. Bonus reading:

Unicode Encoding Conversions with STL Strings and Win32 APIs

 

Member Functions with Generic Parameters

Someone wanted to write a C++ class member function to operate on a generic container.

His thought process was: “Since in C++14 we can use auto with lambda parameters, why not using it also for class method parameters?

class MyClass {
  ...

  // DOESN’T work in C++14!!
  void DoSomething(auto& container) {
    ...

Unfortunately, this code doesn’t compile. In fact, in C++14 “auto” is not a valid parameter type for member functions.

Visual Studio 2015 emits the following error:

error C3533: a parameter cannot have a type that contains ‘auto’

To fix that code, we can use templates. The member function with an “auto” parameter can be written as a member function template:

class MyClass {
  ...

  //
  // Simulate:
  //
  //   void DoSomething(auto& container)
  //
  // using templates.
  //
  template <typename Container>
  void DoSomething(Container& container) {
    ...

Beginner’s Bug: What’s Wrong with Brace-Init and std::vector?

Question: I have some old C++ code that creates a std::vector containing two NUL wchar_ts:

std::vector<wchar_t> v(2, L'\0');

This code works just fine. I tried to modernize it, using C++11’s brace-initialization syntax:

// Braces {} used instead of parentheses () 
// to initialize v
std::vector<wchar_t> v{2, L'\0'};

However, now I have a bug in my new C++ code! In fact, the brace-initialized vector now contains a wchar_t having code 2, and a NUL. But I wanted two NULs! What’s wrong with my code?

Answer: The problem is that the new C++11 brace initialization syntax (more precisely: direct-list-initialization) in this vector case stomps (prevails) on the initialize-with-N-copies-of-X constructor overload that was used in the original code. So, the vector gets initialized with the content of the braced initialization list: {2, L’\0’}, i.e. a wchar_t having code 2, and a NUL.

I’m sorry: to get the expected original behavior you have to stick with the classical C++98 parentheses initialization syntax.

 

Helper Functions to Manage Double-NUL-Terminated Strings

A double-NUL-terminated string is a data structure used in several places on the Win32 platform.

For example, the Windows registry can store double-NUL-terminated strings using the REG_MULTI_SZ type. As another example, the lpstrFilter of the Win32 OPENFILENAME structure points to a buffer containing double-NUL-terminated strings.

I’ve developed a couple of C++ helper functions to create and parse double-NUL-terminated strings: check them out here on GitHub!

 

Getting Write Access to CString’s Internal Buffer

In the MSDN Magazine article “Using STL Strings at Win32 API Boundaries”, I discussed how to use std::wstring with Win32 APIs.

Note: The aforementioned article focuses on std::wstring containing Unicode UTF-16 encoded text; if you are interested in how to convert between an UTF-8 std::string and an UTF-16 std::wstring, this other MSDN Magazine article “Unicode Encoding Conversions with STL Strings and Win32 APIs” can come in handy.

But if you are developing (or maintaining) Windows C++ applications using ATL, WTL or MFC, you already have a convenient string class available for use at the Win32 API boundary: CString.

CString is designed in a way to be very well integrated with Win32 APIs. For example, you can simply pass instances of CString to Win32 APIs taking input string pointers; in other words, CString is a drop-in replacement for LPCTSTR parameters.

Moreover, using CString you can easily load strings from resources (via its LoadString method), format strings in a printf-like way using Format, or in a more advanced form using FormatMessage, etc.

Of course std::wstring has other advantages, like SSO (Small String Optimization), move semantics, STL iterator semantics, working with C++11 range-for loops, good integration with Boost, etc.

If you use ATL, WTL or MFC, many Win32 C-interface APIs are wrapped in a convenient object-oriented interface, and you can simply retrieve strings in CString instances (for example, calling a proper overload of CWindow::GetWindowText).

But what if you want to get a string from a Win32 API that isn’t wrapped in a nice way by the existing ATL/WTL/MFC classes?

In this case, you may need to let the Win32 API to scribble its output in the CString’s internal string buffer. With STL’s wstring you can simply call the wstring::resize method to make enough room in the string, and then pass a pointer to that buffer, as described in the aforementioned MSDN Magazine article.

But how can you access CString’s internal buffer for writing?

Well, you can call a couple of methods of the CString class: GetBuffer and ReleaseBuffer. The usage pattern is as follows:

  1. Call CString::GetBuffer to allocate a sufficiently large internal buffer; on success, this method returns a non-const pointer to the allocated buffer, giving you write access to it.
  2. Call the Win32 API (or whatever function) passing the pointer returned by CString::GetBuffer, so the called function can write its result text in the specified buffer.
  3. Call CString::ReleaseBuffer, which releases the access to CString’s internal buffer, so that the CString object can sync its state to the new buffer content.

Note that if the called function writes a NUL-terminator at the end of the string (as most Win32 APIs usually do), you can simply call CString::ReleaseBuffer, without passing any argument. In fact, in this case, the ReleaseBuffer method will simply scan the string stored in the CString’s internal buffer, until it finds the terminating NUL.

In addition, you can specify an explicit string length value to CString::ReleaseBuffer. In this case, the string in the internal buffer will be considered for that exact length.

Note that in Unicode builds those lengths are expressed in wchar_ts (not in bytes!).

This commented C++ sample code shows CString’s GetBuffer and ReleaseBuffer in action:

CString s;

// Allocate an internal buffer for CString, 
// and get write access to it.
const int bufferSize = 100; // in wchar_ts!
wchar_t* buffer = s.GetBuffer(bufferSize);

// Scribble in the CString's internal buffer.
wcscpy_s(buffer, bufferSize, L"Connie");

// Release access to the internal buffer.
// Now the CString object synchronizes its 
// state with the content of its internal 
// buffer.
//
// NOTE: This assumes that the string 
// in the buffer is *NUL*-terminated!
s.ReleaseBuffer();

// Avoid dangling references.
// After calling CString::ReleaseBuffer
// we cannot touch the CString's internal 
// buffer anymore.
buffer = nullptr;

// Let's check if it works!
ATLASSERT(s == L"Connie");

Note that if you explicitly pass a string length to CString::ReleaseBuffer, the string in the internal buffer is truncated at the specified position; e.g. if you call “s.ReleaseBuffer(3);” only the first three characters in the CString’s internal buffer are considered for the final CString’s text, making s == “Con” in the example above.

P.S. Pay attention when you manipulate CString’s internal buffers. For example, note that CString is not designed to store strings with embedded NULs. In fact, as stated in this MSDN documentation web page (emphasis mine):

“Although it is possible to create CStringT instances that contain embedded null characters, we recommend against it. Calling methods and operators on CStringT objects that contain embedded null characters can produce unintended results.

 

The Unreadable Obscure LPXYSTR Typedefs

If you write Win32 C++ code, you’ll find a lot of unreadable and apparently obscure typedefs for strings, for example: LPCTSTR, LPTSTR, LPCWSTR, etc.

What are those? What do they mean?

The key to understand those apparently obscure (but certainly unreadable!) typedefs is to split their names into smaller parts.

Let’s start with the “decoding” of LPCTSTR:

  • LP means pointer. I think it actually means something like “long pointer”, in a period (16-bit Windows?) when probably there were both “long” (far?) and “short” (near?) pointers, but this predates my experience with the C++ Windows platform, so I just don’t know for sure.
  • C means: const, constant.
  • T means: TCHAR
  • STR means: C-style NUL-terminated string.

So, putting those elements together, an “LPCTSTR” is a “pointer to a read-only (const) NUL-terminated TCHAR string”, i.e. in C and C++ code: “const TCHAR*. You can find LPCTSTR parameters in many Win32 APIs, e.g. in SetWindowText.

Now, to be honest, to me “const TCHAR*” is much more readable than “LPCTSTR”: In fact, using the former, I can clearly see all the composing elements: “const”, “TCHAR”, “pointer”. Instead, in the latter “LPCTSTR” compressed form, the components are zipped together in an obscure unreadable form.

Since I gave a friendly piece of advice to forget about the TCHAR model, let’s substitute “TCHAR” with “wchar_t” in Unicode builds, so LPCTSTR becomes “const wchar_t*”! So, we get basically a pointer to a read-only C-style NUL-terminated Unicode (UTF-16) string.

Let’s do another one: LPTSTR.

  • LP: pointer
  • T: TCHAR
  • STR: NUL-terminated string

So, this is basically like LPCTSTR, but missing the “C” (“const”). So, this is a string buffer that isn’t read-only: you can write into it; for example, think of the output string returned by GetWindowText.

In code, it’s: “TCHAR *”, which is equivalent to “wchar_t*” in Unicode builds. Let’s see: “wchar_t*” vs. “LPTSTR”. Wow! The former (“wchar_t*”) is much simpler and more readable to me!

And let’s be honest that the difference between LPCTSTR and LPTSTR is very subtle: the “C” for “const” is buried in the middle of the LPCTSTR typedef! Instead, the difference between “const wchar_t*” and “wchar_t*” is much more clear!

Finally, let’s analyze LPCWSTR.

  • LP: pointer
  • C: const
  • W: wide, i.e. WCHAR/wchar_t based
  • STR: NUL-terminated string

So, this a pointer to a read-only (const) wchar_t-based (i.e. Unicode UTF-16) NUL-terminated string; in C++ code that translates to “const wchar_t*”. Again, in my opinion the expanded form is much more readable than the obscure “LPCWSTR” typedef. You can find this typedef used e.g. in the DrawThemeTextEx Win32 API.

Let’s summarize these results in a nice table:

Win32 Obscure Typedef Expanded Equivalent Equivalent in Unicode Builds
LPCTSTR const TCHAR * const wchar_t*
LPTSTR TCHAR * wchar_t*
LPCWSTR const wchar_t* const wchar_t*

Decoding other obscure Win32 typedefs is left as an Exercise for The Reader (TM). Actually, I hope those typedefs will now be a little bit less obscure…

Note also that you may find the pointer part sometimes abbreviated using “P” instead of “LP”: Welcome to the New World of (just) pointers, without long/short/near/far pointers 🙂

And, as a coding style, I think that using the underlying C++ types (like in “const wchar_t*”) is much better (e.g. clearer, less bug-prone) than using those Win32 typedefs (like “PCWSTR”).

 

Giovanni Dicanio's C++ Corner on the Internet