запустить тест повреждения памяти glibc вручную

Я получаю

*** glibc detected *** malloc(): memory corruption

ошибки типа. В моем случае их особенно сложно отлаживать, потому что

  1. Среда кросс-компиляции, без valgrind
  2. libc собран без отладочной информации, поэтому загрузка дампа ядра в cross-gdb не дает многого.
  3. Корневая файловая система довольно хрупкая, попытка заменить glibc пересобранной копией приводит к массовым поломкам.
  4. Приложение, вызывающее эти ошибки, начало свою жизнь как предоставленный поставщиком образец C с malloc/free повсюду. Я добавил свой собственный код, который использует интеллектуальные указатели C++ для своего собственного распределения, но все еще есть много устаревших тупых указателей.

Ошибки также возникают, когда я использую #if для удаления добавленного кода, хотя отчеты приходят в другом месте (раньше, если мой код отсутствует, при выходе из приложения, если мой код присутствует). Это не особенно необычно; проблемы с расположением кучи, как известно, чувствительны к расположению памяти.

Я считаю вероятным, что в исходном примере кода где-то было «доброкачественное» превышение, которое топчет что-то важное после того, как я внес изменения. Также возможно, что часть кода, который я удалил из примера, инициализировала указатель, который все еще где-то используется. Или ничего важного не перезаписывается, но при включении отладочной информации с помощью -g появляется больше сообщений о проблемах.

Что еще хуже, пример является многопоточным и делает вызовы сложной библиотеки поставщика также сомнительного качества.

Я хотел бы локализовать повреждение памяти. Есть ли способ вызвать проверку согласованности метаданных кучи glibc вручную, вместо того, чтобы ждать следующего вызова malloc()?


FWIW, ошибка была не в коде, который я написал, и я действительно верю в общественное порицание (и какой-нибудь бедняга, работающий над тем же самым, может сэкономить день, обнаружив это), так что вот. Из ilclient_utils.c по крайней мере в одном из образцов Texas Instruments OpenMAX:

  pAppDataPtr->capILComp->outPortParams =
    malloc (sizeof (IL_CLIENT_OUTPORT_PARAMS) *
            pAppDataPtr->capILComp->numOutport);

  memset (pAppDataPtr->capILComp->outPortParams, 0x0,
          sizeof (IL_CLIENT_OUTPORT_PARAMS) *
          pAppDataPtr->capILComp->numOutport);

  pAppDataPtr->deiILComp->inPortParams =
    malloc (sizeof (IL_CLIENT_INPORT_PARAMS) *
            pAppDataPtr->deiILComp->numInport);

  memset (pAppDataPtr->deiILComp->inPortParams, 0x0,
          sizeof (IL_CLIENT_INPORT_PARAMS));

  pAppDataPtr->deiILComp->outPortParams =
    malloc (sizeof (IL_CLIENT_INPORT_PARAMS) *
            pAppDataPtr->deiILComp->numOutport);
  memset (pAppDataPtr->deiILComp->outPortParams, 0x0,
          pAppDataPtr->deiILComp->numOutport *
          sizeof (IL_CLIENT_OUTPORT_PARAMS));

  pAppDataPtr->encILComp->inPortParams =
    malloc (sizeof (IL_CLIENT_INPORT_PARAMS) *
            pAppDataPtr->encILComp->numInport);
  memset (pAppDataPtr->encILComp->inPortParams, 0x0,
          sizeof (IL_CLIENT_INPORT_PARAMS));

  pAppDataPtr->encILComp->outPortParams =
    malloc (sizeof (IL_CLIENT_INPORT_PARAMS) *
            pAppDataPtr->encILComp->numOutport);
  memset (pAppDataPtr->encILComp->outPortParams, 0x0,
          sizeof (IL_CLIENT_OUTPORT_PARAMS));

  pAppDataPtr->disILComp->inPortParams =
    malloc (sizeof (IL_CLIENT_INPORT_PARAMS) *
            pAppDataPtr->disILComp->numInport);
  memset (pAppDataPtr->disILComp->inPortParams, 0x0,
          sizeof (IL_CLIENT_INPORT_PARAMS));

Обратите внимание, что два из приведенных выше выделений памяти используют sizeof (IL_CLIENT_INPORT_PARAMS), но должны были использовать sizeof (IL_CLIENT_OUTPORT_PARAMS). Да здравствует C++ и типобезопасность new []!


К этому коду прилагается обязательное уведомление:

/*
 *  Copyright (c) 2010-2011, Texas Instruments Incorporated
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *  *  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *  *  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *  *  Neither the name of Texas Instruments Incorporated nor the names of
 *     its contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 *  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 *  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 *  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 *  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 *  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *  Contact information for paper mail:
 *  Texas Instruments
 *  Post Office Box 655303
 *  Dallas, Texas 75265
 *  Contact information:
 *  http://www-k.ext.ti.com/sc/technical-support/product-information-centers.htm?
 *  DCMP=TIHomeTracking&HQS=Other+OT+home_d_contact
 *  ============================================================================
 *
 */

person Ben Voigt    schedule 17.06.2013    source источник


Ответы (2)


Похоже, один из способов

#include <mcheck.h>

mcheck_check_all();

Документация не очень подробная, но кажется, что этот mcheck.h является встроенной проверкой glibc, которая уже запущена во время распределения.

person Ben Voigt    schedule 17.06.2013

включение отладочной информации с -g приводит к тому, что сообщается о большем количестве проблем.

Обнаружение повреждения кучи glibc работает не иначе.

Есть ли способ вызвать проверку согласованности метаданных кучи glibc вручную

Да: http://www.gnu.org/software/libc/manual/html_node/Heap-Consistency-Checking.html См. также MALLOC_CHECK_ описание переменных среды.

person Employed Russian    schedule 17.06.2013
comment
MALLOC_CHECK_ вызывает запуск проверки согласованности во время malloc(). Я специально попросил способ запустить проверку между вызовами malloc. - person Ben Voigt; 17.06.2013
comment
Также обратите внимание, что я не говорил, что -g был способом включить проверку, а просто сказал, что я получаю больше отчетов после включения -g. Ошибки кучи чувствительны ко многим вещам, включая структуру памяти, а многопоточные программы с ошибками чувствительны ко всему, что влияет на синхронизацию, возможно, включая размер двоичного файла. - person Ben Voigt; 17.06.2013