简体   繁体   English

C ++ - 如何在lldb / Xcode中获取std :: vector对象的地址

[英]C++ - how to obtain address of std::vector object in lldb / Xcode

I have a stack-allocated std::vector that is being overwritten by some rogue code. 我有一个堆栈分配的std::vector ,被一些流氓代码覆盖。 It is not the data being overwritten, but the internal state. 它不是被覆盖的数据 ,而是内部状态。 I know this because the size() member function returns a junk value some time into the program. 我知道这是因为size()成员函数在程序中返回一段垃圾值。 It initialises correctly. 它正确初始化。 I suspect a common pointer bug elsewhere in my code. 我怀疑代码中的其他地方有一个常见的指针错误。

I am using Xcode 4.6.2 . 我正在使用Xcode 4.6.2 I want to set a hardware breakpoint (with lldb ) upon memory access to the vector's first memory location (of the vector itself, not the data), so I can see what is overwriting it. 我想在内存访问向量的第一个内存位置(向量本身,而不是数据)时设置硬件断点(使用lldb ),所以我可以看到覆盖它的内容。 According to this I need to first find the address of the vector. 根据这个我需要先找到矢量的地址。 Normally one would use the & operator to get the address of a variable, but for some reason with lldb this doesn't return the address but instead prints some sort of summary string. 通常会使用&运算符来获取变量的地址,但由于某种原因,使用lldb这不会返回地址,而是打印某种类型的汇总字符串。

class myClass {
 public:
  myClass() : myVector(4) {}
 private:
  std::vector<double> myVector;
  double myDouble;
};

After breaking at an arbitrary breakpoint after everything is constructed: 在构造完所有内容后,在任意断点处断开之后:

(lldb) frame variable &myObject.myVector
(std::vector<double, std::allocator<double> > *) $7 = size=4

'expr' has the same result: 'expr'具有相同的结果:

(lldb) expr &myObject.myVector;
(std::vector<double, std::allocator<double> > *) $8 = size=4

Normally I'd expect to see the address printed, such as with this plain data member: 通常我希望看到打印的地址,例如使用此普通数据成员:

(lldb) frame variable &myObject.myDouble
(double *) &myDouble = 0x0000000125589328

I tried assigning the address to a variable with 'expr' but that doesn't work either: 我尝试使用'expr'将地址分配给变量,但这也不起作用:

(lldb) expr std::vector<double, std::allocator<double> > * f = &myObject.myVector; f
(std::vector<double, std::allocator<double> > *) $12 = size=0

The zero size (instead of 4) returned there suggests it didn't actually pick up the right vector anyway. 返回的零大小(而不是4)表明它实际上并没有实际获取正确的向量。

So how do I get the address of this vector? 那么如何获取此向量的地址? If I right-click on it in Xcode's list of frame variables, and choose 'View Memory' of this vector, then it opens a view of 0x0 which of course is invalid. 如果我在Xcode的帧变量列表中右键单击它,并选择此向量的“查看内存”,则会打开0x0的视图,当然这是无效的。 Note that the vector is allocated on the stack - it's actually inside a few other objects but all of these are stack constructed. 请注意,向量是在堆栈上分配的 - 它实际上位于其他几个对象中,但所有这些都是堆栈构造的。

Please note that I am not wanting to obtain the address of the data within the vector - this isn't actually being overwritten. 请注意,我不想得到矢量内的数据的地址-这实际上没有被覆盖。 It is the internal storage of the stack-allocated vector object that is being damaged. 它是堆栈分配的矢量对象的内部存储,正在被损坏。

Your myObject object is likely a local variable and exists on the stack: 您的myObject对象可能是一个局部变量并存在于堆栈中:

(lldb) p &myObject
(myClass *) $0 = 0x00007fff5fbffad8
(lldb) p $fp >= &myObject && &myObject >= $sp
(bool) $1 = true

If you want lldb to not pretty-print the vector, use the -R / --raw-output option to frame variable : 如果你想让lldb不漂亮地打印向量,请使用-R / --raw-output选项来frame variable

(lldb) fr va -R myObject
(myClass) myObject = {
  myVector = {
    std::_Vector_base<double, std::allocator<double> > = {
      _M_impl = {
        _M_start = 0x00000001001008d0
        _M_finish = 0x00000001001008f0
        _M_end_of_storage = 0x00000001001008f0
      }
    }
  }
  myDouble = 6.95322297580907e-310
}

You'll notice the addresses on the vector are heap addresses - that is, they were malloc 'ed ( new 'ed, whatever) instead of being located inside your myObject directly. 您会注意到向量上的地址是堆地址 - 也就是说,它们是mallocnew 'ed,无论如何),而不是直接位于myObject So now you have to decide what you want to monitor. 所以现在你必须决定你想要监控什么。 If you want to monitor the vector to see a new element being added to the end of your vector, then you want to watch the end-of-vector pointer, 如果你想监视向量以查看添加到向量末尾的新元素,那么你想要观察向量结束指针,

(lldb) p &myObject.myVector._M_impl._M_finish
(double **) $4 = 0x00007fff5fbffae0

If you want to monitor the contents of one of the vectors, say the first, then you want to monitor 如果你想监视其中一个向量的内容,比如说第一个,那么你想监视

(lldb) p myObject.myVector._M_impl._M_start
(double *) $6 = 0x00000001001008d0

of course when elements are added to the vector it may be moved to a new address range (if the memory region on the heap cannot be grown to hold the new element) so this is going to be a little fragile. 当然,当元素被添加到向量时,它可以被移动到新的地址范围(如果堆上的内存区域不能生成以保存新元素),那么这将会有点脆弱。

Normally lldb's type formatters (for std::vector in this case) are preferable to seeing the raw implementation -- but if you want to work with the raw implementation, it may be easier to disable the formatters in this case. 通常lldb的类型格式化程序(对于本例中的std::vector )比查看原始实现更可取 - 但是如果你想使用原始实现,在这种情况下可能更容易禁用格式化程序。 eg 例如

(lldb) type category disable  gnu-libstdc++
(lldb) p myObject
(myClass) $9 = {
  (std::vector<double, std::allocator<double> >) myVector = {
    (std::_Vector_base<double, std::allocator<double> >) std::_Vector_base<double, std::allocator<double> > = {
      (std::_Vector_base<double, std::allocator<double> >::_Vector_impl) _M_impl = {
        (double *) _M_start = 0x00000001001008d0
        (double *) _M_finish = 0x00000001001008f0
        (double *) _M_end_of_storage = 0x00000001001008f0
      }
    }
  }
  (double) myDouble = 6.95322297580907e-310
}

You can see all of the type formatters built-in to lldb with the type summary list command. 您可以使用type summary list命令查看lldb内置的所有类型格式化程序。

Just as an addendum, you should have been able to say: (lldb) watchpoint set expression &myVector even if you don't really get to “see” the value 就像一个附录一样,你应该能够说:( lldb)观察点设置表达式和myVector,即使你没有真正“看到”这个值

Also, what you were seeing was the summary for an std::vector - turns out that we were not instructing the summary to either not apply to pointers or to show the value as well. 另外,你看到的是std :: vector的摘要 - 结果是我们没有指示摘要不适用于指针或显示值。

I have made a fix to the open source LLDB that will allow you to see the numeric value of the pointer. 我已经修改了开源LLDB,它允许您查看指针的数值。 Probably, the really correct solution, though, would have to be a special “for-pointers” summary format that shows value & summary. 但是,真正正确的解决方案可能必须是一种特殊的“指针”摘要格式,它显示了价值和摘要。 However, I am not overly enthusiastic with going down that route as it would duplicate the amount of regexp formatters we have in LLDB, which is potentially not the best thing to do for performance. 然而,我并不过分热衷于沿着这条路走下去,因为它会复制我们在LLDB中使用的正则表达式格式化程序的数量,这可能不是最好的表现。

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

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