【问题标题】:Why can't I access value in a vector using "print" in gdb debugger?为什么我不能在 gdb 调试器中使用“打印”访问向量中的值?
【发布时间】:2013-01-26 23:17:21
【问题描述】:

我正在学习使用 gdb 调试器,但是当该向量包含从另一个向量复制的值时,我无法访问该向量的值。最终,下面的程序做了我想做的事情(将“nums”的值复制到一个新的向量“copyOfNums”中),但是当我在“copyNums”中执行第一个 for 循环后尝试检查 copyOfNums[0] 的值时",无法访问内存中的值(请参阅下面的 gdb 会话)。

copy nums下面已经执行了for语句的1个循环,所以copyNums[0]应该包含nums[0]指向的值的地址还是应该包含一个新int的引用(与nums[0]) 指向的 l 值?无论如何,我希望能够访问该值,但正如您从以下 gdb 输出中看到的那样,它是不可访问的。

Breakpoint 1, copyNums (nums=@0x7fff5fbffad0) at main.cpp:10

(gdb) print nums[0]
$1 = (int &) @0x100103910: 2
(gdb) print copyOfNums[0]
$2 = (int &) @0x0: Cannot access memory at address 0x0
(gdb) 

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>

using namespace std;

vector<int> copyNums(vector<int> nums){
  int sizeNums = nums.size();
  vector<int> copyOfNums;

=>for (int i = 0; i < sizeNums; i++){
    copyOfNums.push_back(nums[i]);
  }

  return copyOfNums;
}

vector<int> getSmallNums(){

  vector<int> nums;
  nums.push_back(2);
  nums.push_back(1);
  nums.push_back(8);

  return nums;
}

int main (int argc, char *argv[]){
    vector<int> nums = getSmallNums();
    vector<int> copyOfNums = copyNums(nums);


    return 0;
}

这是 sort 返回后的 gbd 输出。看起来副本包含对内存中新位置的引用,其左值为 2(如预期的那样)。为什么我无法在函数 copyNums 中访问 c​​opyOfNums[0]?

(gdb) print nums[0]
$3 = (int &) @0x1001000e0: 2
(gdb) print copyOfNums[0]
$4 = (int &) @0x100103920: 2

编辑:这是调试会话的更完整图片

(gdb) info locals
i = 1
sizeNums = 3
copyOfNums = {
  <std::_Vector_base<int,std::allocator<int> >> = {
    _M_impl = {
      <std::allocator<int>> = {
        <__gnu_cxx::new_allocator<int>> = {<No data fields>}, <No data fields>},
      members of std::_Vector_base<int,std::allocator<int> >::_Vector_impl:
      _M_start = 0x0,
      _M_finish = 0x0,
      _M_end_of_storage = 0x0
    }
  }, <No data fields>}
(gdb) print copyOfNums[0]
$1 = (const int &) @0x0: Cannot access memory at address 0x0

【问题讨论】:

  • 我建议您将copyNums 的声明更改为:vector&lt;int&gt; copyNums(vector&lt;int&gt; const &amp;nums) 您的代码将整个整数向量复制到堆栈中,以按值传递,而您只需要传递一个常量引用。
  • 计算以#include &lt;iostream&gt;开头的行号,然后第10行的断点在int sizeNums = nums.size();处停止执行。 copyOfNums此时没有元素,你是用gdb next 还是step 进入循环的?
  • 哎呀,我通过调试会话删除了部分内容,在该会话中,我在初始中断后多次点击“下一个” - 所以此时它已经经历了一次循环迭代。
  • 另外,感谢关​​于将其更改为 const &nums 的建议!
  • 您可以尝试使用-gstab+ 编译器选项编译它并尝试再次调试它(我在DWARF 2 中遇到过类似问题)?

标签: c++ vector gdb


【解决方案1】:

我不确定编译器能优化多少,但实际上,这段代码:

vector<int> copyNums(vector<int> nums){
  int sizeNums = nums.size();
  vector<int> copyOfNums;

  for (int i = 0; i < sizeNums; i++){
    copyOfNums.push_back(nums[i]);
  }

  return copyOfNums;
}

与这段代码的结果相同:

vector<int> copyNums(vector<int> nums){
  return nums;
}

如果编译器正在执行类似的优化,或许多其他可能的优化,copyofNums 可能会被完全优化掉。

【讨论】:

  • user2016050 应该尝试在禁用所有优化并启用调试的情况下进行编译。如果问题没有重现,那么就是这样。
  • 嗯,我在 Linux 上用g++ -O3 -g 试过这个,gdb 显示确实有一个copyOfNums 适合我。
  • 我使用 makefile 来编译它(这也是我的新手),所以我修改它看起来像: OBJS = main.o CC = g++ DEBUG = -g -O0 CFLAGS = -Wall -c $(DEBUG) LFLAGS = -Wall $(DEBUG) p1 : $(OBJS) $(CC) $(LFLAGS) $(OBJS) -o p1 main.o : main.cpp $(CC) $(CFLAGS) main.cpp clean: \rm *.o *~ p1 tar: tar cfv p1.tar main.cpp
  • 对不起,我草率地粘贴了它-它在真实文件中的格式正确,基本上我只是在DEBUG中的-g之后添加了-O0。这是你推荐的吗?
  • 好吧,在我的测试中,我认为 gcc 可能会将其优化为 -O0。例如,clang 在调试器下的行为与您预期的不同。
【解决方案2】:

让我回答你的部分问题。

copyNums[0] 包含 nums[0] 指向的值的地址或 它是否应该包含对新 int 的引用(与 nums[0]) 指向的左值?

您使用的术语(新的、参考的)让我感到困惑。

copyNums[0] 包含num[0] 的值的副本&amp;nums[0]&amp;copyNums[0] 不同。而nums[0] 包含int 类型的值。因此,copyNums[0] 既不包含位置 nums[0] 的地址,也不包含对新 int 的引用。

【讨论】:

  • 抱歉——我使用的术语令人困惑。当我运行 whatis numCopy[0] 时,我看到它是一个 int&,这意味着它包含一个地址,对吗?指向 int 的地址?我一直认为我理解指针,然后我意识到我还没有 100% 在那里......
猜你喜欢
  • 2011-09-06
  • 2021-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-09
  • 1970-01-01
相关资源
最近更新 更多