为什么 gdb 不能在 !=/== 和 &&/||组合在一个表达式中?

Why can't gdb evaulate functions when !=/== and &&/|| are combined in an expression?

本文关键字:一个 表达式 不能 gdb 为什么 组合      更新时间:2023-10-16

可能是我在描述问题时遇到的困难是我找不到其他人提供它的实例的原因。我使用的是gdb 7.4-2012.04。

似乎至少任何一个表达式都包含这两者和&/||for矢量或矢量迭代器将无法在gdb中进行求值,并出现以下错误:

无法访问地址0x0 处的内存

下面是一个测试用例,后面是我的编译行和测试:

#include <stdio.h>
#include <iostream>
#include <stdint.h>
#include <vector>
using namespace std;
typedef char GUID[32];
int main(int argc, char **argv){
    vector<int> vec;
    for (int i=0; i<5; i++){
        vec.push_back(i);
    }
    for (vector<int>::iterator vecIter=vec.begin(); vecIter!=vec.end(); vecIter++){
        int i=0;//Just need a line gdb will recognize for a breakpoint.
    }
    cout << vec[0] << endl;//g++ needs to include operator[] in the binary for this to work.
    return 0;
}

以下是我执行的测试片段:

user@comp$ g++ -g -O0 any_test.cpp
user@comp$ gdb a.out
(gdb) b 16
(gdb) r
Breakpoint 1, main (argc=1, argv=0x7fffffffe288) at any_test.cpp:16
16          int i=0;//Just need a line gdb will recognize for a breakpoint.
(gdb) p *vecIter == vec[1] or *vecIter == vec[2]
Cannot access memory at address 0x0

原来有用的语句不起作用。让我们减少一点,找出问题所在。

(gdb) p vec[1] or *vecIter == vec[2]
Cannot access memory at address 0x0
(gdb) p vec[1] or *vecIter
$1 = true
(gdb) p 1 or *vecIter == vec[2]
Cannot access memory at address 0x0

问题似乎是"或"之后的"=="。其他运营商也是这样吗?

(gdb) p 1 and *vecIter == vec[2]
Cannot access memory at address 0x0
(gdb) p 1 and *vecIter != vec[2]
Cannot access memory at address 0x0

这是一个响亮的肯定。如果我拔出gdb的所有函数呢?让它取消引用并比较int?

(gdb) p 1 or *vecIter._M_current == vec._M_impl._M_start[1]
$2 = true

好的,让我们检查一些取消引用和函数的组合,以确保问题不仅仅是由以下类型之一引起的:

(gdb) p 1 or *vecIter._M_current == *vecIter
Cannot access memory at address 0x0
(gdb) p 1 or vec._M_impl._M_start[1] == vec[1]
Cannot access memory at address 0x0

正如您所看到的,问题并不特别在于向量或其迭代器。如果在&amp;/||,并且在===/!=的任一侧。

编辑:又忘了一个问题。我的问题是:为什么我在"p*vecIter==vec[1]或*vecIter==vec[2]"行中得到"无法访问地址0x0处的内存"?

问题出在返回引用的函数中。这里有一个最小的例子:

int& g() { static int i; return i; }
int main() {}

同样的问题也出现了(我使用的是gdb 7.8.1):

(gdb) p 0 || +g()
Cannot access memory at address 0x0

一种变通方法是将引用转换为指针并间接引用:

(gdb) p 0 || +*&g()
$1 = true

提交了一个错误:https://sourceware.org/bugzilla/show_bug.cgi?id=17904

求值"*vecIter==vec[1]"的顺序是先求值*vecIter,如果为true,则跳过求值vec[1],整个语句为true;如果为false,则评估vec[1]。这里的根本原因是vecIter指向无法访问的NULL内存,而*vecIter甚至无法计算。因此gdb打印出"内存访问"错误。

相同错误的其他打印语句的相同原因