2010-01-26 3 views
2

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

#0 0x0017c30c in _IO_flush_all_lockp() from /lib/libc.so.6 
#1 0x0017d030 in _IO_cleanup() from /lib/libc.so.6 
#2 0x0013e042 in exit() from /lib/libc.so.6 
#3 0x00126bbe in __libc_start_main() from /lib/libc.so.6 
#4 0x08049d11 in _start() 

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

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

Редактировать: Кто-то сказал, что это связано с visual_mem_new0. Эта функция просто выделяет память. Он ничего не знает о плагине-> авторе.

Редактировать: Duh. Память прямо перед strdup заполняет память.

Редактировать: Хорошо, что избавляется от одной утечки памяти. Я не уверен, что начальная трассировка стека связана с утечкой памяти - она ​​все еще существует, например. Он пытается выпустить некоторый ресурс, который я считаю. Часть этой программы использует много скомпилированной сборки (JIT-компилятор), которая использует память mmap'd поверх дескриптора файла для буфера. Я закрываю файл. Есть ли что-то, что мне нужно сделать с картой памяти?

Я буду продолжать пытаться очистить эти утечки памяти с пути. Я недавно что-то сделал, связанный с определенным плагином. Программа работает только при закрытии, когда я запускаю этот плагин, который использует карту памяти, о которой я говорил. Я не уверен, что это может быть. Я внес некоторые незначительные изменения. Первоначально я подозревал общий указатель, что я отслеживаю ссылки. Он использует ту же самую систему, которая используется во всем libvisual, и никаких утечек памяти, характерных для этого, не появляется. Во всяком случае, я надеюсь, что у кого-то есть некоторые подсказки. Я не могу придумать ничего другого.

Редактировать: Хорошо, отследил его с помощью истории изменений. Что случилось со следующим кодом? Могу ли я не копировать выходные данные на себя?

static inline int dump_stack(AvsCompilerContext *ctx) 
{ 
    AvsCompilerArgument *pa; 
    char output[2048]; 

    snprintf(output, 2047, "\ncompiler: stackdump: Stack dump\n"); 
    for (pa=(AvsCompilerArgument *)ctx->stack->base; pa < (AvsCompilerArgument *)ctx->stack->pointer; pa++) { 
     snprintf(stderr, 2047, "%scompiler: stackdump: [%2d] = ", output, (pa - (AvsCompilerArgument *)ctx->stack->base)); 
     switch (pa->type) { 
      case AvsCompilerArgumentInvalid: 
       snprintf(output, 2047, "%sinvalid", output); 
       break; 

      case AvsCompilerArgumentConstant: 
       snprintf(output, 2047, "%s%.2f", output, pa->value.constant); 
       break; 

      case AvsCompilerArgumentIdentifier: 
       snprintf(output, 2047, "%s", pa->value.identifier); 
       break; 

      case AvsCompilerArgumentMarker: { 
       char *markers[] = { "invalid", "function", "argument", NULL }; 
       snprintf(output, 2047, "%s--- %s marker ---", output, markers[pa->value.marker]); 
       break; 
      } 

      case AvsCompilerArgumentPrivate: 
       snprintf(output, 2047, "%sprivate", output); 
       break; 

     } 
     snprintf(output, 2047, "\n"); 
    } 

    avs_debug(print(output)); 
    return VISUAL_OK; 
} 

Масштаб avs_debug ничего не делает. Я прокомментировал его содержание.

+0

Вы знаете, что было бы неплохо иметь исходный код здесь , Часть функции StackOverflow - отвечать на вопросы людей, которые приходят после вас. – Omnifarious

+0

Этот код бесполезен для всех. Проблема заключается в трассировке стека, которая теперь полностью не связана с этим кодом. Код больше не работает для этого вопроса. – Scott

+0

Думаю, вы должны были задать другой вопрос. – ergosys

ответ

1

Поскольку вы делаете strdup(), вы должны освободить значения, используя free(). Я не уверен, что visual_mem_free() звонит free(). Если вы попробуете free() вместо visual_mem_free(), ошибка valgrind исчезнет?

Edit: Ваши snprintf() звонки ошибаетесь:

snprintf(output, 2047, "%sinvalid", output); 

snprintf() является C99, и стандарт говорит (7.19.6.5p2):

Если копирование происходит между объектами, которые перекрывают друг друга , поведение не определено.

Точная инструкция для sprintf() в C89.

Самый простой способ исправить вашу проблему будет что-то вроде:

char init[] = "\ncompiler: stackdump: Stack dump\n"; 
size_t init_len = sizeof init - 1; 
snprintf(output, 2047, "\ncompiler: stackdump: Stack dump\n"); 

следуют: (. Как проверить для внедорожных череде ошибок выше)

snprintf(output+init_len, sizeof output - init_len, "%.2f", pa->value.constant); 

Кроме того, я не уверен, почему вы вызываете snprintf() с stderr в качестве первого аргумента в одном из вызовов. Вы компилируете свой код с включенными предупреждениями?

+0

Да, он звонит бесплатно. Я понял, что случилось. Память выше strdup выделяет память. Нет необходимости в strdup. – Scott

+0

отлично. извините за шум. –

3

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

+0

, как показано на выходе valgrind, вам необходимо проверить, инициализирован ли слот выделенной памятью до того, как назначить слот с помощью strdup. В основном я бы добавил отладку if/printf перед каждым использованием strdup, чтобы убедиться, что целевое местоположение не является допустимым указателем, который должен быть освобожден до того, как быть сбитым. –

+0

Не то, Джастин. Я уточнил в вопросе. @Justin: Это невозможно. Память вновь выделена. 'dup_info = visual_plugin_info_new();' Создает недавно выделенный VisPluginInfo, который является memset для NULL. В этом пространстве памяти ничего не сохранилось. – Scott

+0

Подождите, вы правы. Меморандум заключает сделку. – Scott

0

Есть, вероятно, по крайней мере, 2 проблемы в последнем фрагменте кода вы публикуемую (редактирование вопроса оставляет вещи очень запутанной, как к тому, что проблема, которую вы пытаетесь справиться с прямо сейчас):

  1. у вас есть строка, которая начинается snprintf(stderr, 2047, etc...). Это почти наверняка ошибка копирования-вставки, поскольку она не должна компилироваться. Вероятно, вы использовали fprintf().

  2. Вы не можете использовать буфер назначения также в качестве источника в вашем snprintf() вызова. В стандарте говорится: «Если копирование происходит между перекрывающимися объектами, поведение не определено». Если вы подумаете об этом на мгновение, вы можете понять, что он не может работать в общем случае без предварительного копирования буфера где-то в другом месте. Попробуйте создать обертку вокруг vsnprintf() (возможно, с именем snprintfcat()), которая объединяет форматированную строку в буфер назначения. Это не слишком сложно сделать, хотя для этого требуется использовать varargs, который может быть немного сложным - но только немного.

Ниже полностью непроверенной выстрел на snprintfcat() функции - это компилируется, но за пределами этого использования на свой страх и риск:

int snprintfcat(char* dest, size_t siz, char const* fmt, ...) 
{ 
    size_t len = strnlen(dest, siz); 
    size_t remainder = 0; 
    int result; 

    va_list ap; 

    if (len < siz) { 
     remainder = siz - len; 
    } 

    va_start(ap, fmt); 
    result = vsnprintf(dest+siz-remainder, remainder, fmt, ap); 
    va_end(ap); 

    return result + siz - remainder; 
} 
Смежные вопросы