Vickster Vickster - 2 months ago 19
C++ Question

How does the C++ STL vector template store its objects in the Visual Studio compiler implementation?

I am extending the Visual Studio 2003 debugger using autoexp.dat and a DLL to improve the way it displays data in the watch window. The main reason I am using a DLL rather than just the basic autoexp.dat functionality is that I want to be able to display things conditionally. e.g. I want to be able to say "If the name member is not an empty string, display name, otherwise display [some other member]"

I'm quite new to OOP and haven't got any experience with the STL. So it might be that I'm missing the obvious.

I'm having trouble displaying vector members because I don't know how to get the pointer to the memory the actual values are stored in.

Am I right in thinking the values are stored in a contiguous block of memory? And is there any way to get access to the pointer to that memory?

Thanks!

[edit:] To clarify my problem (I hope):

In my DLL, which is called by the debugger, I use a function called ReadDebuggeeMemory which makes a copy of the memory used by an object. It doesn't copy the memory the object points to. So I need to know the actual address value of the internal pointer in order to be able to call ReadDebuggeeMemory on that as well. At the moment, the usual methods of getting the vector contents are returning garbage because that memory hasn't been copied yet.

[update:]

I was getting garbage, even when I was looking at the correct pointer _Myfirst because I was creating an extra copy of the vector, when I should have been using a pointer to a vector. So the question then becomes: how do you get access to the pointer to the vector's memory via a pointer to the vector? Does that make sense?

Answer

The elements in a standard vector are allocated as one contiguous memory chunk.

You can get a pointer to the memory by taking the address of the first element, which can be done is a few ways:

std::vector<int> vec;
/* populate vec, e.g.: vec.resize(100); */

int* arr = vec.data();   // Method 1, C++11 and beyond.
int* arr = &vec[0];      // Method 2, the common way pre-C++11.
int* arr = &vec.front(); // Method 3, alternative to method 2.

However unless you need to pass the underlying array around to some old interfaces, generally you can just use the operators on vector directly.

Note that you can only access up to vec.size() elements of the returned value. Accessing beyond that is undefined behavior (even if you think there is capacity reserved for it).

If you had a pointer to a vector, you can do the same thing above just by dereferencing:

std::vector<int>* vecptr;

int* arr = vecptr->data(); // Method 1, C++11 and beyond.
int* arr = &(*vecptr)[0];  // Method 2, the common way pre-C++11.
int* arr = &vec->front();  // Method 3, alternative to method 2.

Better yet though, try to get a reference to it.

About your solution

You came up with the solution:

int* vMem = vec->_Myfirst;

The only time this will work is on that specific implementation of that specific compiler version. This is not standard, so this isn't guaranteed to work between compilers, or even different versions of your compiler.

It might seem okay if you're only developing on that single platform & compiler, but it's better to do the the standard way given the choice.