简体   繁体   English

C ++ STL矢量模板如何在Visual Studio编译器实现中存储其对象?

[英]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. 我正在使用autoexp.dat和DLL扩展Visual Studio 2003调试器,以改进它在监视窗口中显示数据的方式。 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. 我使用DLL而非仅使用基本的autoexp.dat功能的主要原因是我希望能够有条件地显示内容。 eg 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. 我对OOP还是很陌生,还没有使用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. 在调试器调用的DLL中,我使用了一个称为ReadDebuggeeMemory的函数,该函数可复制对象使用的内存。 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. 因此,我需要知道内部指针的实际地址值,才能同时对其调用ReadDebuggeeMemory。 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. 即使当我正在查看正确的指针_Myfirst时,我也变得很垃圾,因为当我应该一直使用指向矢量的指针时,我正在创建矢量的额外副本。 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? 那有意义吗?

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. 但是,除非您需要将基础数组传递给某些旧接口,否则通常可以直接在vector上使用运算符。

Note that you can only access up to vec.size() elements of the returned value. 请注意,您最多只能访问返回值的vec.size()元素。 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. 如果您仅在单个平台和编译器上进行开发,则似乎可以,但是最好根据选择的标准方法进行开发。

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. 但是,请注意,更改矢量大小的操作(例如push_back)会导致重新分配矢量,这意味着内存可能会移动,从而使指针无效。 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

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. 一旦我从拥有向量变量更改为拥有指向向量的指针,就无法实现GmanRoddy建议的解决方案,这很可能是因为我太笨了。

I have found the pointer I was looking for though: _Myfirst 我找到了我一直在寻找的指针:_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. 我能够访问_Myfirst很惊讶。 I would have expected it to be a private member. 我本来希望它是私人会员。 But obviously not... 但显然不是...

You couldn't implement the solutions suggested by Gman and Roddy because they answers, seemingly correct, but has nothing to do with you situation. 您无法实施Gman和Roddy建议的解决方案,因为它们可以回答,看似正确,但与您的情况无关。

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. 当开发用于与autoexp.dat一起使用的表达式评估(EE)的Addin Dll时,您将从过程中获得一个指向矢量对象的原始指针。 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. 但是Dll在Visual Studio调试器的过程中运行,因此访问矢量数据的唯一方法是通过ReadDebuggeeMemory函数。

You should use that raw pointer and ReadDebuggeeMemory() to read the memory occupied by an object in Debugee process to the local buffer/object. 您应该使用该原始指针和ReadDebuggeeMemory()将Debugee进程中的某个对象占用的内存读取到本地缓冲区/对象。 (local for Debugger process, meaning your dll). (对于Debugger进程是本地的,表示您的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. 然后,如果它是指针,则从本地对象获取必要的数据,然后必须再次使用ReadDebuggeeMemory()来将其指向的对象读取到另一个本地位置。 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. 对于矢量对象(我自己还没有做过具体介绍),您应该1.将矢量对象读取(ReadDebuggeeMemory())到本地对象。 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. 2.获取向量的大小(我假设它是向量类中的非指针数据)。3.获取指向该连续内存位置的指针,并将该块读取(ReadDebuggeeMemory())到本地缓冲区/块。 Block size is sizeof(VectorType) * VectorSize in bytes. 块大小为sizeof(VectorType)* VectorSize(以字节为单位)。 (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. 4.由于向量包含指针,因此必须将每个项目分别读取(ReadDebuggeeMemory())到本地存储器中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM