【问题标题】:Evaluating an expression with overloaded operators in c++ lldb在 C++ lldb 中使用重载运算符评估表达式
【发布时间】:2013-12-21 16:21:52
【问题描述】:

我正在使用 lldb 在 Xcode 5 中调试 C++ 程序,我想在调试器中评估任意表达式,尤其是那些使用重载运算符的表达式。

例如,我创建了一个非常简单的 Xcode 5 C++ 项目,其中包含以下 main.cpp 和所有编译器/链接器/等选项设置为默认值:

#include <iostream>
#include <vector>

int main(int argc, const char * argv[])
{
  std::vector<int> vec;
  vec.push_back(42);
  std::cout << "vec[0] = " << vec[0] << std::endl;
  return 0;
}

我在return 0; 行设置断点并运行程序。

然后,在 lldb 提示符下,将向量作为一个整体打印就可以了:

(lldb) expr vec
(std::__1::vector<int, std::__1::allocator<int> >) $0 = size=1 {
  [0] = 42
}

但是,我无法使用重载的operator[] 访问其成员:

(lldb) expr vec[0]
error: call to a function 'std::__1::vector<int, std::__1::allocator<int> >::operator[](unsigned long)' ('_ZNSt3__16vectorIiNS_9allocatorIiEEEixEm') that is not present in the target
error: The expression could not be prepared to run in the target

同样,我无法获取迭代器(虽然我在这里经验较少,所以我的语法可能是错误的):

(lldb) expr vector<int>::iterator it = vec.begin()
error: use of undeclared identifier 'vector'
error: expected '(' for function-style cast or type construction
error: expected '(' for function-style cast or type construction
error: 3 errors parsing expression

(lldb) expr (vector<int>::iterator) vec.begin()
error: use of undeclared identifier 'vector'
error: expected '(' for function-style cast or type construction
error: expected '(' for function-style cast or type construction
error: 3 errors parsing expression

类似地,打印一个简单的字符串也可以正常工作:

(lldb) expr string("a")
(std::__1::string) $0 = "a"

但是,简单的字符串连接失败:

(lldb) expr string("a") + string("b")
error: invalid operands to binary expression ('string' (aka 'std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >') and 'string')
error: 1 errors parsing expression

我做错了什么? lldb 是否支持重载运算符的求值?

提前谢谢你!

【问题讨论】:

  • 帧变量 vec[0] 应该可以打印向量中的元素
  • 啊,确实有效,谢谢@EnricoGranata。但是,它不适用于获取向量迭代器或连接字符串。所以我是那里的 1/3。
  • 我不确定为什么 vec[0] 在表达式中不起作用,但是如果您在源代码中使用 vec.begin(),那么您应该可以说 expr vec.begin( );试着在你的 main() 中调用 begin()

标签: c++ xcode lldb


【解决方案1】:

我刚刚遇到了同样的问题,显然找到了一个简单的解决方法。 您可以像这样访问矢量vec 的第 i 个元素:

(lldb) p vec.__begin_[i]
(int) $1 = 100

【讨论】:

  • 非常感谢这个提示,它对我很有帮助。如果有关于让 lldb 评估 C++ 表达式并执行诸如执行 vec.size() 之类的方法的更新,我想知道。可以gdb吗?
  • 读者注意:“开始”后有一个单下划线!谢谢,它有效!
【解决方案2】:

请注意,C++ 标准库的设置是为了内联所有可以合理内联的模板化函数,并且不存在真正的函数副本。因此,例如,当您拨打std::vector&lt;int&gt;::begin() 时,没有这样的功能。它的所有用途都已内联。

这就是为什么您会收到有关“调用函数......目标中不存在”的错误。可能有函数的内联副本,但没有一个我们可以实际调用。举个例子,如果我构建了一个小 C++ 程序,它创建了一个 std::vector,并将一些元素推送到它上面,然后迭代它们,然后执行:

    (lldb) image lookup -r -n begin
    2 matches found in /private/tmp/vector:
        Address: vector[0x0000000100000eaf] (vector.__TEXT.__text + 1071)
        Summary: vector`main + 1071 [inlined] std::__1::vector<int, std::__1::allocator<int> >::begin() at vector.cpp:12
                 vector`main + 1071 at vector.cpp:12        Address: vector[0x0000000100000eaf] (vector.__TEXT.__text + 1071)
        Summary: vector`main + 1071 [inlined] std::__1::vector<int, std::__1::allocator<int> >::begin() at vector.cpp:12
                 vector`main + 1071 at vector.cpp:12

所以std::vector&lt;int&gt; 的所有开始和结束访问器实例都是内联的。以及来自 std c 库本身的部分:

12 matches found in /usr/lib/libc++.1.dylib:
    Address: libc++.1.dylib[0x000000000003e4ec] (libc++.1.dylib.__TEXT.__text + 252188)
    Summary: libc++.1.dylib`std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::begin()        Address: libc++.1.dylib[0x000000000003e51c] (libc++.1.dylib.__TEXT.__text + 252236)
    Summary: libc++.1.dylib`std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::begin() const        Address: libc++.1.dylib[0x000000000003e574] (libc++.1.dylib.__TEXT.__text + 252324)

还有一些basic_string,仅此而已。所以没有我们可以调用的任何真正的实现。然后,一旦我们对这些 std 对象的真实世界只有一点点可用,当你开始推动它时,世界会以其他奇怪的方式分崩离析。

lldb 目前还不够聪明,无法弄清楚如何从 C++ 标准库的头文件中重构模板化函数/方法。我们没有足够的环境来编译您的代码来完成该任务。

请注意,这并不是重载运算符的真正问题,而是编译器使用 std 库的方式的问题。对于您自己的类,事情应该会更好,因为在 -O0 处没有那么多内联。

【讨论】:

  • 谢谢,这很好地解释了为什么我无法通过 lldb 调用某些表达式。但是,如果我真的想要调用这些表达式,最好的解决方法是编写我自己的调用内联函数的包装函数,然后从 lldb 调用该包装函数?
  • Apple 管理自己的编译器的重点不应该是他们可以提供这样的端到端集成吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-07-24
  • 1970-01-01
  • 1970-01-01
  • 2011-09-16
  • 2022-01-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多