首页 文章

在c lldb中使用重载运算符计算表达式

提问于
浏览
17

我正在使用lldb在Xcode 5中调试一个C程序,我想在调试器中评估任意表达式,特别是那些使用重载运算符的表达式 .

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

#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是否支持使用重载运算符进行评估?

先感谢您!

2 回答

  • 20

    请注意,C标准库已设置为可以内联所有可以明智内联的模板化函数,并且不存在实际的函数副本 . 例如,当你去调用 std::vector<int>::begin() 时,没有这样的功能 . 它的所有用途都已内联 .

    这就是为什么你会遇到“调用函数...目标中不存在”的错误 . 可能有函数的内联副本,但我们实际上无法调用 . 作为一个例子,如果我构建一个生成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<int> 的开始和结束访问器的所有实例都是内联的 . 更进一步来自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,而这就是全部 . 所以我们没有任何真正的实现可以调用 . 然后,一旦我们只得到了我们可用的这些标准物体的真实世界,当你开始推动它时,世界就会以其他奇怪的方式崩溃 .

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

    请注意,这对于重载运算符来说并不是一个问题,编译器使用std库的方式更是一个问题 . 事情应该对你自己的课程更好,在-O0没有那么多的内联 .

  • 24

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

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

相关问题