挂在 std::cout 上的 GDB 调试器

Posted

技术标签:

【中文标题】挂在 std::cout 上的 GDB 调试器【英文标题】:GDB debugger hanging on std::cout 【发布时间】:2016-06-27 21:21:21 【问题描述】:

由于我的学习,我已经编写 C 和 C++ 代码有一段时间了。我们曾经在学校的编码课程中使用 Visual Studio 作为 IDE。

我现在正在尝试学习使用 GNU 编译器工具和调试器。我使用的是 CodeLite IDE 版本 9.1.8,带有 TDM-GCC-64 5.1.0 编译器。

我的具体问题是 GDB 调试器。我对它的用法有些熟悉(Step into、Step over 等)。每次我尝试调试自己的任何代码时,调试器都会在断点处正常停止并让我从那里继续。

但是,每次我用调试器点击“cout”时,它都拒绝进入下一行。当遇到带有“cout”的行时,我按“F10”转到下一行,但调试器不会从那里继续。它总是冻结,不响应任何命令,我必须强制关闭调试器。其他所有可以想象的陈述都可以,但不是任何形式的“cout”。

熟悉 CodeLite 的人可能都知道调试时文本编辑器窗口左边缘的绿色箭头。当箭头击中“cout”并且我按“F10”进入下一行时,箭头闪烁。当我再次按下“F10”时,箭头再次闪烁。在箭头从左侧边栏中完全消失并且调试器挂在那里之前,这可以完成大约 3-4 次。

Starting debugger

Debugger hanging and arrow disappeared

这是一个示例代码。它是芬兰语,所以你可能不明白我要打印的内容,但这并不重要。

“Henkilo”类包含两个私有变量,字符串代表姓名,int 代表年龄。还有<<操作符被重载了,可以让cout直接打印对象。这段代码的赋值是为了演示复制构造函数的使用。

#include <iostream>
#include "Henkilo.h"


int main()

    Henkilo henkilo1;

    henkilo1.setName("Jaakko");
    henkilo1.setAge(24);

    Henkilo henkilo2(henkilo1);

    std::cout << "\nLuotiin henkil\2241, jonka tiedot ovat: " << std::endl << henkilo1 << std::endl;
    std::cout << "Kopioitiin henkil\2241 objektiin henkil\2242. Henkil\224n 2 tiedot ovat: " << henkilo2 << std::endl;
    return 0;

请原谅我在发布此内容时可能犯的任何错误,这是我第一次。

编辑:

@KennyOstrom

是的,我可以进入该功能,现在我已经对其进行了测试。它似乎也挂在那里。

std::ostream& operator<< (std::ostream& os, const Henkilo& obj) 
    os << "\nNimi : " << obj.name<< std::endl << "Ik\204 : " << obj.age << std::endl; 
    return os;

它似乎挂在您将字符串文字插入“os”对象的行。

编辑:

@PaulMcKenzie

抱歉,根本没有考虑这一点。这是该类的实现。这是一个人的基本类,具有姓名和年龄字段。

Henkilo.h

#include <string>
#include <iostream>

class Henkilo

private:
    std::string name;
    int age;
public:
    Henkilo();
    Henkilo(std::string initName, int initAge);
    Henkilo(const Henkilo& henkilo);
    void setName(std::string newName);
    std::string getName();
    void setAge(int newAge);
    int getAge();
    friend std::ostream& operator<< (std::ostream& os, const Henkilo& obj);
    ~Henkilo();

;

Henkilo.cpp

#include "Henkilo.h"

Henkilo::Henkilo() : name(""), age(0) ;
Henkilo::Henkilo(std::string initName, int initAge) : name(initName), age(initAge) ;
Henkilo::Henkilo(const Henkilo& henkilo) : name(henkilo.name), age(henkilo.age) ;

void Henkilo::setName(std::string newName)  name = newName; ;
std::string Henkilo::getName()  return name; ;
void Henkilo::setAge(int newAge)  age = newAge; ;
int Henkilo::getAge()  return age; ;

std::ostream& operator<< (std::ostream& os, const Henkilo& obj) 
 
    os << "\nNimi : " << obj.name<< std::endl << "Ik\204 : " << obj.age << std::endl;
    return os;

Henkilo::~Henkilo() ;

【问题讨论】:

如果你只尝试一个空字符串std::cout &lt;&lt; "" &lt;&lt; std::endl;,它允许你跳过它吗?这可能是工具中的错误报告,而不是代码中存在的错误。 不,它仍然挂起。但是,它确实会在其后打印空字符串和换行符。这个问题也是 Dev-C++ 和 Code::Blocks IDE 的问题。 你能进入处理操作符 对这个离题很抱歉。有人刚刚编辑了我的帖子,我不小心删除了更改:D 请随时将其编辑为更好的形式。 @JoonasOnatsu 你真的应该发一个minimal reproducible example。您说它是调试器,但是您发布的内容中存在未知数。 Henkilo 类和你在里面做什么是未知的。它可能会破坏内存,从而破坏输出流的工作方式。也许Henkilooperator &lt;&lt; 有问题,您处于无限循环中。你也有这个:Henkilo henkilo2(henkilo1); 调用复制构造函数,我们不知道它是如何实现的。您应该将我们都可以复制/粘贴/运行的代码发布到代码编辑器中,编译并运行应用程序。 【参考方案1】:

看起来您的输出流运算符重载并没有返回任何内容。你在第一行之后有你的 return 语句,它后面什么都没有。试试这个:

std::ostream& operator<< (std::ostream& os, const Henkilo& obj) 
  os << "\nNimi : " << obj.name<< std::endl << "Ik\204 : " << obj.age << std::endl; 
  return os;

【讨论】:

FFS。对不起,我糟糕的 *** 使用技能:D 原始复制粘贴的代码包含正确的返回语句。 是这个问题吗? 不,我的原始代码和你的一样。我只是碰巧搞砸了我粘贴的代码。

以上是关于挂在 std::cout 上的 GDB 调试器的主要内容,如果未能解决你的问题,请参考以下文章

gdb 调试多线程

检查 gdb 中的模板参数包

linux内核调试技术之GDB和GDBServer

gdb调试Alpine Linux上的OpenJDK java失败了“线程接收信号?,未知信号”

[QNX Hypervisor 2.2用户手册]7.1 使用GNU调试器(GDB)

GDB调试系列之了解GDB