【问题标题】:visual studio has triggered a breakpoint Poco NotificationCentervisual studio 已触发断点 Poco NotificationCenter
【发布时间】:2015-01-15 13:50:16
【问题描述】:

我收到消息“VS 已触发断点”的问题,当我在那里中断时,VS 跳转到 POCO NotificationCenter 的源代码:

我正在使用 Poco 1.5.4。

调用堆栈中的上一个条目位于以下代码段中:

void WebSocketController::HandleReceivedMessages() {
    AutoPtr<Notification> notification(receivedMessagesQueue.waitDequeueNotification());

    while (!messageHandlerActivity.isStopped() && notification) {
        MessageNotification* messageNotification = dynamic_cast<MessageNotification*>(notification.get());
        if (messageNotification)
        {
            notificationCenter.postNotification(messageNotification);
        }

        notification = receivedMessagesQueue.waitDequeueNotification();
    }
}

我在调用堆栈中看到的具体行(带有行号)如下:

notification = receivedMessagesQueue.waitDequeueNotification();

这是 MessageNotification.h 的代码:

    class MessageNotification : public Notification
    {
    public:
        MessageNotification(Message *data);
        ~MessageNotification();
        Message* GetData();
    private:
        Message *data;
    };

这是 MessageNotification.cpp 的代码:

    MessageNotification::MessageNotification(Message *data) {
        this->data = data;
    }

    MessageNotification::~MessageNotification() {
        delete data;
        data = nullptr;
    }

    Message* MessageNotification::GetData() {
        return data;
    }

在这里你可以看到 Message 类的构造函数:

        Message::Message(const MessageCommandEnum cmd, const string& to, StringMap *params, const string& data)
            : cmd(cmd), to(to), data(data) {
            this->params = params == nullptr ? new StringMap() : params;
        }

        Message::Message(const Message& msg) : to(msg.to), cmd(msg.cmd), data(msg.data) {
            params = new StringMap(*msg.params);
        }

        Message::Message(const Message* msg) : to(msg->to), cmd(msg->cmd), data(msg->data) {
            params = new StringMap(*msg->params);
        }

        Message::~Message() {
            if (params != nullptr) {
                delete params;
                params = nullptr;
            }
        }

这个类的其余方法只是getter/setter。

知道为什么会这样吗?

我的研究告诉我,如果堆被破坏,就会出现此消息。但我找不到任何应该发生这种情况的代码行。 这种行为有点奇怪,因为当我在消息上按继续时,应用程序运行没有任何问题。当应用程序没有在后台使用调试器启动时,我没有任何问题(例如,在 Debug 文件夹中启动 exe)。

我仍在学习 C++,因此非常感谢任何反馈/帮助。

谢谢

【问题讨论】:

  • 由于它发生在ObserverList 复制构造上,并且由于ObserverList 是智能指针std::vector 的类型定义(这应该很安全),我怀疑堆粉碎。这意味着您在堆上的另一个对象的边界之外写入,而该对象恰好位于内存中被粉碎对象的正前方(您是否使用任何持有本地缓冲区的对象?char[],也许?)或通过无效恰好指向不幸对象的指针。删除后使用某些内容是获得该内容的好方法。当然,这都是猜测。
  • 获取 Microsoft Application Verifier 并启用堆检查以查看您是否损坏了明显的内容。
  • 我无法找出 Microsoft Application Verifier 的任何问题 - 日志总是提到零错误和零警告。
  • 不——没有本地缓冲区——恐怕。但很明显,问题与“notification = receivedMessagesQueue.waitDequeueNotification();”行有关。重新启动后,我不再得到 VS 描述的异常。现在,每次有新通知可用时,我都会收到通知变量地址的写访问冲突。这对我来说没有意义?!?

标签: c++ visual-c++ poco-libraries


【解决方案1】:

WebSocketController::HandleReceivedMessages() 中的 AutoPtr 通知将在您为它分配另一个指针后立即被 AutoPtr 删除。但是,此时,指针被传递到另一个 AutoPtr 中的 NotificationCenter,并且您稍后尝试取消引用(或 AutoPtr 尝试删除)它的任何位置,都会导致未定义的行为。

将通知指针放入 AutoPtr 后,只需将其作为 AutoPtr 传递(使用 notification.cast() 进行投射)。 另外,MessageNotification 构造函数指针参数永远不会传入,因为您从未构造 MessageNotification 对象(您只是将 Notification* 动态转换为 MessageNotification*)。

查看NotificationQueue example 以了解如何正确执行此操作。

【讨论】:

  • 你好亚历克斯!感谢您的帮助 - 我会立即尝试。非常感谢!
  • 好的,看看我对 MessageNotification 构造函数参数的评论,我想你可能确实在其他地方传递了它,所以你可以忽略它。作为一个经验法则 - 永远不要将 AutoPtr 与裸指针混合。如果您绝对必须将 AutoPtr 分配给一个指针,请确保您手动调用 duplicate()/release()(即永远不要在任何时候对包装在 AutoPtr 中的指针调用 delete)。
  • 而且,查看代码,您似乎使用的是手动 lock()/unlock(),这是不安全的。按照this answer 中的建议使用ScopedLock。 BTW,你能接受答案吗?谢谢。
  • 否 - 没有手动锁。题外话:我需要在任何地方同步我使用 ScopedLock 的东西(正如你向我展示的那样)。 MessageNotification 在其他地方创建(queue.enqueueNotification(new MessageNotification(message)); - message 是一个指针)。我已将我的代码调整为 NotificationQueue 示例,现在我使用 notification.cast 而不是 dynamic_cast。我还清理了我的代码,以确保我不会遇到由混淆 AutoPtr 和裸指针引起的问题。代码现在正在运行,没有任何异常。非常好!非常感谢!
  • 也许应该根据 NotificationQueue 示例更新幻灯片 28 上的文档 here
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-12
  • 1970-01-01
  • 1970-01-01
  • 2021-12-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多