Член класса std::string поврежден строковым литералом, зарегистрированным сторонним макросом

Резюме:

У меня есть класс, реализующий разделяемую память с использованием Boost Interprocess. Ошибка сегментации происходит из метода read() который получает доступ к named_condition, Когда я смотрю на значения поблизости std::string Члены класса в ГБД они тоже испорчены. Один содержит значение строкового литерала, который я регистрирую только через сторонний макрос.

Я собираюсь описать проблему, показать вам код, который устанавливает предполагаемые строковые значения, а затем спросить, являюсь ли я причиной проблемы, или это сторонний регистратор?

Я использую Clang (не GCC).

Эту проблему невероятно сложно воспроизвести. Это происходит один раз каждые 300+ запусков.

Подробности:

Это мой объект, содержащий Boost Interprocess named_condition и рядом std::string s, которые я заметил, имели искаженные значения:

char                                        a[1000];     
std::shared_ptr<bip::named_mutex>           mutex{nullptr};
char                                        b[1000];     
MyVector*                                   vec{nullptr};
std::shared_ptr<bip::managed_shared_memory> segment{nullptr};
std::shared_ptr<bip::named_condition>       cond_empty;                 // Seg fault 
bool                                        destroy_memory{false};
std::string                                 shared_vector_name;         // Weird value
std::string                                 shared_mutex_name;          // Weird value 
std::string                                 shared_cv_name;             // Weird value
std::string                                 shared_memory_name;         // Weird value
std::string                                 tag_name;

Два массива символов были добавлены несколько недель назад для обнаружения (вероятно, того же самого) сбоя сегментации.

Ошибка сегментации возникает, когда я пытаюсь получить доступ к named_condition при попытке прочитать общую память:

std::vector<T> read(const bool clearAfterReading, const bool readImmediately = false)
{
    checkMemory();   // Loops over 'a' and checks for corruption
    std::vector<T> readItems;
    std::cout << "Reader trying to obtain mutex" << std::endl;

    bip::scoped_lock<bip::named_mutex> lock(*sdc.mutex);

    if(sdc.vec->empty() && readImmediately == false)
    {
        std::cout << "Reader waiting. vec size: " << sdc.vec->size() << std::endl;
        sdc.cond_empty->wait(lock);       //SEG FAULT OCCURS HERE

Когда я смотрю на состояние sdc.cond_empty в GDB, я замечаю m_base = 0x0:

(gdb) p *(sdc.cond_empty._M_ptr)
$12 = {m_cond = {m_shmem = {<boost::interprocess::ipcdetail::managed_open_or_create_impl_device_holder<false, boost::interprocess::shared_memory_object>> = {<No data fields>}, static ManagedOpenOrCreateUserOffset = 16, 
      m_mapped_region = {m_base = 0x0, m_size = 104, m_page_offset = 0, m_mode = boost::interprocess::read_write, m_is_xsi = false}}}}

поэтому я предполагаю, что я прав, что это named_condition было повреждено?

Затем я решил проверить значения окружающих членов класса std::string (прокрутите вправо до конца):

(gdb) p sdc.shared_vector_name
$22 = {static npos = <optimized out>, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0x7fff80a0d438 "HandleRunRequest()"}}
(gdb) p sdc.shared_mutex_name
$23 = {static npos = <optimized out>, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0x7fff80a0d468 "File exists"}}
(gdb) p sdc.shared_cv_name
$24 = {static npos = <optimized out>, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0x7fff80a0d498 "/abc_shared_memory"}}
(gdb) p sdc.shared_memory_name
$25 = {static npos = <optimized out>, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0x7fff80a0d408 ""}}
(gdb) p sdc.tag_name
$26 = {static npos = <optimized out>, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0x7fffc021d598 "abc"}}

и я замечаю, что их значения совершенно неверны. Похоже, что значения получены из строковых литералов, которые я записываю через сторонний макрос.

Предполагаемые значения std::string устанавливаются с помощью следующего кода:

Это const:

extern "C" 
{
    const std::string ABC_SH_MEM_NAME = "abc";
}

передается через конструктор чтения общей памяти:

sharedMemReader(CONSTS::ABC_SH_MEM_NAME, CONSTS::ABC_SH_MEM_SIZE, true),

через аргумент тега:

SharedDataReader(const std::string& tag, const int numBytes, const bool destroyMemory)
{
    sdc.initialise(tag, numBytes, destroyMemory);

так что жестко закодированные строки могут быть добавлены к tag и назначается вышеупомянутым членам класса string:

void initialise(const std::string& tag, const int numBytes, const bool ownMemory)
{
    std::cout << std::endl << "Started initialisation..." << std::endl;

    const std::string sharedMemoryName = tag + "_shared_memory";
    const std::string sharedVectorName = tag + "_shared_vector";
    const std::string sharedMutexName = tag + "_shared_mutex";
    const std::string sharedCVName = tag + "_shared_cv";

    tag_name = tag;
    shared_memory_name = sharedMemoryName;
    shared_mutex_name = sharedMutexName;
    shared_vector_name = sharedVectorName;
    shared_cv_name = sharedCVName;
    destroy_memory = ownMemory;

Как упоминалось ранее, shared_vector_name поврежден значением "HandleRunRequest()".

Мое единственное использование этой строки / значения - это вызов стороннего макроса регистрации:

void MyClass::HandleRunRequest() 
{
    THIRD_PARTY_LOG_MACRO("HandleRunRequest()");

но этот метод не вызывается сразу-рядом read() где происходит ошибка сегмента. Этот метод вызывает несколько других методов перед созданием нового потока, который затем вызывает read(),

Могу ли я что-нибудь сделать, чтобы вызвать эту коррупцию? Или стороннее ведение журнала хранит значения в случайных адресах указателя?

У меня все еще есть дамп ядра и библиотека, но учтите, что эту проблему невероятно сложно воспроизвести.

0 ответов

Другие вопросы по тегам