views:

991

answers:

4

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?

+3  A: 

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:

std::vector<int> vec;

int *array = &vec[0]; // method 1
int *array = &vec.front(); // method 2

However, you can just use the operators available to access the vector, unless you really need a raw pointer.

Edit

Now that you have a pointer to a vector, you can do the same thing above:

std::vector<int> *vec;

int *array = &vec->operator[](0); // method 1
int *array = &vec->front(); // method 2

Method 2 seems rather clean, but you could just dereference to get back to the original solution:

std::vector<int> *vec;

int *array = &(*vec)[0]; // method 1
int *array = &(*vec).front(); // method 2

I think this can be made more elegant by design. For example, do you have to get the vector by pointer? If so, use int *array = &vec->front();, since that seems most concise.

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 your very implementation of that compiler versio. This is not-standard, so this probably won't work between compilers, or even different version of your compiler.

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

GMan
That's true for Visual Studio. But standard does not mention "contiguous memory" for `vector`.
Kirill V. Lyadvinsky
The original standard did't, but there have been updates (TCs). The current standard requires contiguous allocation.
anon
So Visual Studio 2003 uses contiguous allocation?
Vickster
Yes. In fact all C++ implementations, past and present, do so.
anon
Great! Thank you
Vickster
If you find mine or Roddy's answer helpful, please mark one of them as correct.
GMan
What if they are both correct, but not actually helpful to me? They don't answer the question I was trying to ask. (Yes, I'm aware that could be my fault for asking badly. I did my best...)
Vickster
Hm, I didn't see your edit. I don't understand what you need, though :(
GMan
Oops, I was asking the question wrong. Or rather, I was going about the whole thing slightly wrong (vector instead of pointer to vector).Thanks for trying to help!
Vickster
I have changed my implementation to your method 2. Thank you very much!!!
Vickster
No problem. :-)
GMan
+3  A: 

Yes, The values are stored in a contiguous area of memory, and you can take the address of the first element to access it yourself.

However, be aware that operations which change the size of the vector (eg push_back) can cause the vector to be reallocated, which means the memory may move, invalidating your pointer. The same happens if you use iterators.

vector<int> v;

v.push_back(1);

int* fred = &v[0];

for (int i=0; i<100; ++i)
  v.push_back(i);

assert(fred == &v[0]); // this assert test MAY fail
Roddy
Indeed, the standard iterator invalidation rules for vectors apply.
Frerich Raabe
A: 

I couldn't implement the solutions suggested by Gman and Roddy once I changed from having a vector variable to having a pointer to a vector, quite probably because I'm just too clueless.

I have found the pointer I was looking for though: _Myfirst

So my code works when I use

std::vector<int>* vec;

int *vMem = vec->_Myfirst;

I'm surprised that I've got access to _Myfirst. I would have expected it to be a private member. But obviously not...

Vickster
anon
A: 

You couldn't implement the solutions suggested by Gman and Roddy because they answers, seemingly correct, but has nothing to do with you situation.

When developing an Addin Dll for Expression Evaluation (EE) to use with autoexp.dat, you are getting one raw pointer to the vector object from your process. But the Dll is running in the process of Visual Studio Debugger, so the only way to access the vector's data is through the ReadDebuggeeMemory function.

You should use that raw pointer and ReadDebuggeeMemory() to read the memory occupied by an object in Debugee process to the local buffer/object. (local for Debugger process, meaning your dll). Then get necessary data from local object, if it is a pointer, than you have to use ReadDebuggeeMemory() again, to read the object pointed by it to another local location. And so on.

For vector's (I haven't done it myself to be more specific), you should 1. Read (ReadDebuggeeMemory()) the vector object to the local one. 2. Get the size of the vector (I assume it is a non pointer data in vector class) 3. Get the pointer to that the contiguous memory location, and read (ReadDebuggeeMemory()) that block to the local buffer/block. Block size is sizeof(VectorType) * VectorSize in bytes. (if it is not continuous, then things will be more complicated, but the idea is the same). 4. Since your vector contains pointers, you have to read (ReadDebuggeeMemory()) every item separately into local memory.

resak