Valgrind在说new的行中看到了删除
Valgrind sees delete in the line that says new
当我检查应用程序是否存在内存泄漏时,我遇到了一个非常特殊的valgrind行为。据我所知,他看到了以下代码
virtual ServiceHandler* createServiceHandler(StreamSocket& socket)
/// Create and initialize a new ServiceHandler instance.
///
/// Subclasses can override this method.
{
return new ServiceHandler(socket, *_pReactor);
}
作为一个分配和释放内存的地方。此代码是POCO库的一部分,可以在此处找到。下面是valgrind的日志示例,说明提供的return语句同时导致new和delete。
Invalid read of size 8
==9764== at 0x1C63DC: Poco::Net::Socket::operator!=(Poco::Net::Socket const&) const (Socket.h:340)
==9764== by 0x1C2A5C: SocketHandler::onReadableNotification(Poco::AutoPtr<Poco::Net::ReadableNotification> const&) (SocketHandler.cpp:67)
==9764== by 0x1CA0DF: Poco::NObserver<SocketHandler, Poco::Net::ReadableNotification>::notify(Poco::Notification*) const (NObserver.h:88)
==9764== by 0x5C04077: Poco::NotificationCenter::postNotification(Poco::AutoPtr<Poco::Notification>) (NotificationCenter.cpp:78)
==9764== by 0x579F422: Poco::Net::SocketNotifier::dispatch(Poco::Net::SocketNotification*) (SocketNotifier.cpp:80)
==9764== by 0x579C0DC: Poco::Net::SocketReactor::dispatch(Poco::AutoPtr<Poco::Net::SocketNotifier>&, Poco::Net::SocketNotification*) (SocketReactor.cpp:282)
==9764== by 0x579BEE1: Poco::Net::SocketReactor::dispatch(Poco::Net::Socket const&, Poco::Net::SocketNotification*) (SocketReactor.cpp:258)
==9764== by 0x579B5F4: Poco::Net::SocketReactor::run() (SocketReactor.cpp:114)
==9764== by 0x5C50406: Poco::(anonymous namespace)::RunnableHolder::run() (Thread.cpp:57)
==9764== by 0x5C500E0: Poco::ThreadImpl::runnableEntry(void*) (Thread_POSIX.cpp:349)
==9764== by 0x6D20493: start_thread (pthread_create.c:333)
==9764== by 0x78BBAFE: clone (clone.S:97)
==9764== Address 0x10c8f908 is 40 bytes inside a block of size 352 free'd
==9764== at 0x4C2D2DB: operator delete(void*) (vg_replace_malloc.c:576)
==9764== --> by 0x19D1CD: Poco::Net::SocketAcceptor<SocketHandler>::createServiceHandler(Poco::Net::StreamSocket&) (SocketAcceptor.h:166)
==9764== by 0x19B3E3: Poco::Net::SocketAcceptor<SocketHandler>::onAccept(Poco::Net::ReadableNotification*) (SocketAcceptor.h:157)
==9764== by 0x1A1385: Poco::Observer<Poco::Net::SocketAcceptor<SocketHandler>, Poco::Net::ReadableNotification>::notify(Poco::Notification*) const (Observer.h:86)
==9764== by 0x5C04077: Poco::NotificationCenter::postNotification(Poco::AutoPtr<Poco::Notification>) (NotificationCenter.cpp:78)
==9764== by 0x579F422: Poco::Net::SocketNotifier::dispatch(Poco::Net::SocketNotification*) (SocketNotifier.cpp:80)
==9764== by 0x579C0DC: Poco::Net::SocketReactor::dispatch(Poco::AutoPtr<Poco::Net::SocketNotifier>&, Poco::Net::SocketNotification*) (SocketReactor.cpp:282)
==9764== by 0x579BEE1: Poco::Net::SocketReactor::dispatch(Poco::Net::Socket const&, Poco::Net::SocketNotification*) (SocketReactor.cpp:258)
==9764== by 0x579B5F4: Poco::Net::SocketReactor::run() (SocketReactor.cpp:114)
==9764== by 0x5C50406: Poco::(anonymous namespace)::RunnableHolder::run() (Thread.cpp:57)
==9764== by 0x5C500E0: Poco::ThreadImpl::runnableEntry(void*) (Thread_POSIX.cpp:349)
==9764== by 0x6D20493: start_thread (pthread_create.c:333)
==9764== Block was alloc'd at
==9764== at 0x4C2C21F: operator new(unsigned long) (vg_replace_malloc.c:334)
==9764== --> by 0x19D19E: Poco::Net::SocketAcceptor<SocketHandler>::createServiceHandler(Poco::Net::StreamSocket&) (SocketAcceptor.h:166)
==9764== by 0x19B3E3: Poco::Net::SocketAcceptor<SocketHandler>::onAccept(Poco::Net::ReadableNotification*) (SocketAcceptor.h:157)
==9764== by 0x1A1385: Poco::Observer<Poco::Net::SocketAcceptor<SocketHandler>, Poco::Net::ReadableNotification>::notify(Poco::Notification*) const (Observer.h:86)
==9764== by 0x5C04077: Poco::NotificationCenter::postNotification(Poco::AutoPtr<Poco::Notification>) (NotificationCenter.cpp:78)
==9764== by 0x579F422: Poco::Net::SocketNotifier::dispatch(Poco::Net::SocketNotification*) (SocketNotifier.cpp:80)
==9764== by 0x579C0DC: Poco::Net::SocketReactor::dispatch(Poco::AutoPtr<Poco::Net::SocketNotifier>&, Poco::Net::SocketNotification*) (SocketReactor.cpp:282)
==9764== by 0x579BEE1: Poco::Net::SocketReactor::dispatch(Poco::Net::Socket const&, Poco::Net::SocketNotification*) (SocketReactor.cpp:258)
==9764== by 0x579B5F4: Poco::Net::SocketReactor::run() (SocketReactor.cpp:114)
==9764== by 0x5C50406: Poco::(anonymous namespace)::RunnableHolder::run() (Thread.cpp:57)
==9764== by 0x5C500E0: Poco::ThreadImpl::runnableEntry(void*) (Thread_POSIX.cpp:349)
==9764== by 0x6D20493: start_thread (pthread_create.c:333)
我在有趣的部分添加了-->
。
一旦发生这种情况,我会观察到更多类似的日志,因为对象似乎没有被分配。在我看到这个错误之前,这个应用程序正常工作了一段时间,这是第一个发生的错误。我认为这个错误可能发生在套接字行为不好的时候。
我使用以下命令对应用程序进行评估
valgrind --vgdb=yes --vgdb-error=0 app
并使用gdb来进一步检查代码。
我的问题是:
- 为什么valgrind告诉我所提供的代码同时调用new和delete
- 这种行为是由本地代码引起的,还是应该在其他地方查找问题
@编辑
ctor
SocketHandler::SocketHandler(StreamSocket &socket, SocketReactor &reactor) :
_socket(socket) /* copy */, _reactor(reactor) /* reference */ {
_socket.setBlocking(false);
_reactor.addEventHandler(_socket, NObserver<SocketHandler, ReadableNotification>(*this,
&SocketHandler::onReadableNotification));
_reactor.addEventHandler(_socket,
NObserver<SocketHandler, ErrorNotification>(*this, &SocketHandler::onErrorNotification));
_reactor.addEventHandler(_socket, NObserver<SocketHandler, ShutdownNotification>(*this,
&SocketHandler::onShutdownNotification));
_addr = _socket.peerAddress().toString();
}
Valgrind消息并不表示您在同一行代码中有一个new和一个delete。
valgrind错误消息包含3个堆栈跟踪。
第一个堆栈跟踪是检测到错误的位置。此错误包括读取已释放的一段内存。
然后Valgrind试图给你更多关于这段记忆的信息。为此,它向您显示了2个额外的堆栈跟踪:
第二个堆栈跟踪指示在哪里释放了这段内存。第三个堆栈跟踪指示这段内存的分配位置。
换句话说:您的代码首先分配了一段内存(位于堆栈跟踪编号3)。然后,您的代码释放了这段内存(位于堆栈跟踪号2)。然后您的代码错误地访问了这段内存(在堆栈跟踪nr 1处)。
所以,这一切看起来就像你有一个真正的错误:你使用了一个悬空的指针,指向释放的内存。
您可能需要查看生成的代码,才能确切地看到为createServiceHandler调用生成了哪些对new/delete的调用。显然,在"新建"answers"删除"堆栈跟踪中有两条不同的指令(0x19D1CD和0x19D19E)。
正如Bo Persson在评论中所建议的,删除是由构造函数中未处理的异常引起的。在ctor中捕获相关异常,并将抛出异常的表达式移动到负责注册事件处理程序的行之前
SocketHandler::SocketHandler(Poco::Net::StreamSocket &socket, SocketReactor &reactor) :
_socket(socket), _reactor(reactor) {
try {
_socket.setBlocking(false);
_addr = _socket.peerAddress().toString();
_reactor.addEventHandler(_socket, NObserver<SocketHandler, ReadableNotification>(*this,
&SocketHandler::onReadableNotification));
_reactor.addEventHandler(_socket,
NObserver<SocketHandler, ErrorNotification>(*this,
&SocketHandler::onErrorNotification));
_reactor.addEventHandler(_socket, NObserver<SocketHandler, ShutdownNotification>(*this,
&SocketHandler::onShutdownNotification));
} catch (Exception& e) {
// Handle POCO exception
} catch (...) {
// Handle ellipsis
}
}
无效的内存访问不再存在。_socket.peerAddress()
在尝试获取不再连接的套接字的地址时引发异常。起初,我认为ctor中的任何异常都会导致应用程序迅速崩溃,但在Poco::Net::SocketReactor
中,每个未处理的异常都会传递给ErrorHandler
。这就是为什么应用程序即使在抛出未处理的异常后仍能继续工作的原因。参考代码可以在这里找到:126。
- 是否删除在对象构造过程中创建的对象
- 比较 2 个向量并从第二个向量中删除在第一个 - c++ 中找不到的元素
- 删除在结构 c++ 中声明的数组元素
- 如何删除在另一个函数中初始化的动态分配数组
- "删除"在 g++ 中抛出错误,同时在 clang 中完美编译
- 删除和删除[]在内部如何工作?
- 从主函数中删除在另一个函数中使用 new 创建的一系列对象
- 如何删除在函数中创建的动态数组
- 使用delete []删除在堆内存上创建的一系列数组
- C :如何正确删除在类破坏者中的指针
- 无法删除在destructor中的成员指针的课程
- 如何删除在没有STL的队列中存储在数组中的第一个字符串元素
- 删除或删除 [] 在新的 int[][] 上
- Valgrind在说new的行中看到了删除
- 如何避免删除在C++中作为参数给出的对象
- 我什么时候应该使用删除?(在动态创建的2D数组之后未删除的后果)
- 析构函数删除在 main 中声明的动态数组
- 删除在向量上的传播
- C 有人可以解释这些循环在说什么
- C :删除在堆栈上声明的结构的字段