Как я могу отладить память cra sh, если sanitizer ничего не показывает? - PullRequest
0 голосов
/ 22 января 2020

У меня сложное приложение, которое вылетает при выходе. Я не могу воспроизвести ошибку с минимальным примером. Cra sh происходит, когда деструктор для класса вызывается при выходе из приложения, и разделяемый член-указатель уничтожается. В основном я делаю следующее:

// plugin (.so loaded at runtime)
// called during application run
void SomePluginClass::foo()
{
    auto ptr = std::make_shared<int>();
    libraryObj.bar(ptr);
}

// library (.so linked to the executable and the plugin)
// SomeLibraryClass.hpp
class SomeLibraryClass
{
public
    // ... some other code

    ~SomeLibraryClass();
    void bar(std::shared_ptr<int> ptr);

private:
    std::shared_ptr<int> m_ptr{};
}

// SomeLibraryClass.cpp
// called during application run
void SomeLibraryClass::bar(std::shared_ptr<int> ptr) { m_ptr = ptr; }

// called on application exit and cleanup
SomeLibraryClass::~SomeLibraryClass()
{
    // crash happens here
    // use_count shows 1
    // reset() used here for debugging purposes as it causes the same crash as implicit destructor call
    m_ptr.reset();
}

Я пытался запустить приложение с помощью Valgrind и g cc адресного дезинфицирующего средства - они оба не показывают никаких проблем во время выполнения, но показывают проблема после крэ sh. Например, вот несколько строк вывода sanitizer:

==11744==ERROR: AddressSanitizer: SEGV on unknown address 0x7f56b3ba0c20 (pc 0x555ac6680ead bp 0x7ffc9d3ce920 sp 0x7ffc9d3ce910 T0)
==11744==The signal is caused by a READ memory access.
    #0 0x555ac6680eac in std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release() /usr/include/c++/7/bits/shared_ptr_base.h:154
    #1 0x555ac6680b33 in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count() /usr/include/c++/7/bits/shared_ptr_base.h:684
    #2 0x7f56e5e562cd in std::__shared_ptr<int, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr() /usr/include/c++/7/bits/shared_ptr_base.h:1123
    #3 0x7f56e5e56574 in std::__shared_ptr<int, (__gnu_cxx::_Lock_policy)2>::reset() /usr/include/c++/7/bits/shared_ptr_base.h:1235

Что означают числа (pc 0x555ac6680ead bp 0x7ffc9d3ce920 sp 0x7ffc9d3ce910 T0)?

Что еще я могу сделать, чтобы найти источник cra sh?

Ответы [ 2 ]

1 голос
/ 26 января 2020

Что означают числа (p c 0x555ac6680ead bp 0x7ffc9d3ce920 sp 0x7ffc9d3ce910 T0)?

Во время cra sh (которое было вызвано попыткой доступа к адресу 0x7f56b3ba0c20), значения счетчика программы (P C), регистров указателя кадра (BP) и указателя стека (SP) были 0x555ac6680ead, 0x7ffc9d3ce920 и 0x7ffc9d3ce910 соответственно.

Программа значение счетчика соответствует функции std::_Sp_counted_base<...>::_M_release().

Мы не знаем, откуда пришел аварийный адрес 0x7f56b3ba0c20. Он не находится рядом с указателем текущего стека и не выглядит как адрес кучи (хотя это может быть), а также не выглядит как случайный мусор. ASan не имеет ни малейшего представления, откуда поступил этот адрес.

Одно из возможных объяснений: адрес находился в куче, затем он был удален и перемещен в карантин (который ASan использует, чтобы сообщить вам о висячем доступе), но затем карантин емкость был превышен другими delete с, из-за чего ASan «забыл» то, что знал об этом адресе (ASan не может вечно хранить информацию о каждом удаленном блоке памяти - это может привести к запуску Недостаточно памяти).

Можно попытаться увеличить размер карантинного буфера ASan с помощью:

ASAN_OPTIONS=quarantine_size_mb=4096

(по умолчанию 256, увеличивайте до тех пор, пока не закончится память или пока ASan не сообщит, что вы на самом деле получаете доступ к висячей памяти).

0 голосов
/ 22 января 2020

Если вы хотите уничтожить ресурс, выделенный за пределами библиотеки, при уничтожении объекта SomeLibraryClass, вы возитесь с владельцем ресурса. Вы не должны этого делать. Если вы просто хотите освободить ваше совместное владение объектом, управляемым ptr, вам вообще не нужно вызывать m_ptr.reset ().

...