Почему мое значение не увеличивается? Стоп памяти / глюк стека? - PullRequest
1 голос
/ 16 октября 2010

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

Мне кажется, что я видел это раньше, но на этот раз я хочу понять, почему это происходит.

У меня есть:

int i;
int debug = 0;
for(i = 0; i < buf_end; i++) {
    do_some_buffer_work();
    if(something_is_true()) {
         do_something_important();
         printf("debug is %i, i is %i", debug++, i);
    }
}

printf ("end \ n");

, и я получаю в качестве вывода:

debug is 1, i is 55
debug is 2, i is 55

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

int i;
static int debug;
for(i = 0; i < buf_end; i++) {
    do_some_buffer_work();
    if(something_is_true()) {
         do_something_important();
         printf("debug is %i, i is %i\n", debug++, i++);
         printf("debug is %i, i is %i\n", debug++, i++);
         printf("debug is %i, i is %i\n", debug++, i++);
    }
}
printf("end\n");

, и я получил такой интересный вывод:

debug is 0, i is 55
debug is 1, i is 56
debug is 2, i is 57
debug is 3, i is 55
debug is 4, i is 56
debug is 5, i is 57
end

Так что здесь очевидно, что две полные итерации с тем же самым я выполнил, но на переменную отладки это не повлияло.Может показаться, что значение по какой-то причине кэшируется и восстанавливается.У меня была догадка, я изменил переменную отладки на нестатическую и получил это:

int i;
int debug = 0;
for(i = 0; i < buf_end; i++) {
    do_some_buffer_work();
    if(something_is_true()) {
         do_something_important();
         printf("debug is %i, i is %i\n", debug++, i++);
         printf("debug is %i, i is %i\n", debug++, i++);
         printf("debug is %i, i is %i\n", debug++, i++);
    }
}
printf("end\n");

, и я получил такой интересный вывод:

debug is 0, i is 55
debug is 1, i is 56
debug is 2, i is 57
debug is 0, i is 55
debug is 1, i is 56
debug is 2, i is 57
end

Так что это выглядит как переменные, которые живутв стеке сбрасываются до начала 55-й итерации.

Я уверен, что ошибка заключается в одном из этих вызовов do_something_important (), которые имеют дело с чтением буфера, но эта ошибка приняла символсвое собственное, и я думаю, что я обязан уважением узнать больше о его природе, прежде чем раздавить его.Поэтому, пожалуйста, вместо того, чтобы пытаться помочь мне исправить это, дайте мне знать, если у вас есть какая-то подсказка о том, почему это происходит.В частности, что можно изменить в состоянии программы, чтобы «сбрасывать» значения, подобные этим?

Редактировать: Извините, если меня раздражает, что я пропустил функции.Они довольно большие и имеют ссылки на другие функции, но главная причина, по которой я их не упомянул, заключалась в том, что я не забочусь об исправлении этой проблемы;Я хочу знать, как я мог бы воссоздать его самым простым способом.

2-е редактирование: Вот непосредственная функция, где происходит блюз.Включение ссылочной функции и всех подфункций и определений, вероятно, занимает около 500 строк, поэтому я не буду этого делать здесь.

static int find_headers_search(FCALParseContext *fpc, uint8_t *buf, int buf_size,
                               int search_start)

{
    FCALFrameInfo fi;
    int end_offset = -1, size = 0, i;
    uint8_t *header_buf;

    int debug = 0;
    for (i = 0; i < buf_size - 1; i++) {
        if ((AV_RB16(buf + i) & 0xFFFE) == 0xFFF8) {
                av_log(NULL,AV_LOG_DEBUG,"predebug%i i %i\n",debug, i);
            header_buf = fcal_fifo_read_wrap(fpc, search_start + i,
                                             MAX_FRAME_HEADER_SIZE,
                                             &fpc->wrap_buf,
                                             &fpc->wrap_buf_allocated_size);

            if (frame_header_is_valid(header_buf, &fi)) {
                av_log(NULL,AV_LOG_DEBUG,"frame num %u bufstart %u, size %u, end %u i %i\n", (unsigned int)fi.frame_or_sample_num,
                       search_start, buf_size, search_start + buf_size -1, i);
                FCALHeaderMarker **end_handle = &fpc->headers;

                size = 0;
                while (*end_handle) {
                    end_offset =  (*end_handle)->offset;
                    end_handle = &(*end_handle)->next;
                    size++;
                }

                *end_handle = av_mallocz(sizeof(FCALHeaderMarker));
                if (!*end_handle) {
                    av_log(fpc->avctx, AV_LOG_ERROR,
                           "couldn't allocate FCALHeaderMarker\n");
                    return AVERROR(ENOMEM);
                }
                (*end_handle)->fi     = fi;
                (*end_handle)->offset = search_start + i;
                /* The actual size of the linked list is now size + 1 */
                update_sequences(fpc, size - FCAL_MAX_SEQUENTIAL_HEADERS,
                                 FFMIN(size, FCAL_MAX_SEQUENTIAL_HEADERS),
                                 *end_handle);
                fpc->nb_headers_found++;
                size++;
                av_log(NULL,AV_LOG_DEBUG,"debug%i i %i\n",debug++, i++);
                size = 0;
                while (*end_handle) {
                    end_offset =  (*end_handle)->offset;
                    end_handle = &(*end_handle)->next;
                    size++;
                }

                *end_handle = av_mallocz(sizeof(FCALHeaderMarker));
                if (!*end_handle) {
                    av_log(fpc->avctx, AV_LOG_ERROR,
                           "couldn't allocate FCALHeaderMarker\n");
                    return AVERROR(ENOMEM);
                }
                (*end_handle)->fi     = fi;
                (*end_handle)->offset = search_start + i;
                /* The actual size of the linked list is now size + 1 */
                update_sequences(fpc, size - FCAL_MAX_SEQUENTIAL_HEADERS,
                                 FFMIN(size, FCAL_MAX_SEQUENTIAL_HEADERS),
                                 *end_handle);
                fpc->nb_headers_found++;
                size++;
                av_log(NULL,AV_LOG_DEBUG,"debug%i i %i\n",debug++, i++);
                av_log(NULL,AV_LOG_DEBUG,"debug%i i %i\n",debug++, i++);
                av_log(NULL,AV_LOG_DEBUG,"debug%i i %i\n",debug++, i++);
            }
        }
    }
    return size;
}

Ответы [ 4 ]

3 голосов
/ 16 октября 2010

Есть буфер, есть buf_end, есть некоторая «работа с буфером». Все невидимое в сниппете. Ясно, что есть некоторый невидимый код, который пишет после конца буфера, топая локальные переменные debug и i . Установите точку останова данных на конце буфера, и вы найдете ее через минуту или две, обычно.

2 голосов
/ 16 октября 2010

Для меня это похоже на рекурсию / возвращение.Следующая гипотеза объясняет наблюдаемое поведение:

do_some_buffer_work() при некоторых условиях вызывает функцию, содержащую этот код.Это объяснило бы, что статичность согласована, и местные жители перезапускаются.Причина, по которой вы видите его только для определенных значений i, заключается в том, что something_is_true() имеет значение только для этих значений i.

. Вероятно, вам следует добавить код в отладчик.Наблюдение за стеком вызовов в точке останова вашего printf () быстро определит, произошла ли рекурсия.

1 голос
/ 16 октября 2010

Это может быть или не быть полезным (незнание того, что do_some_buffer_work(), something_is_true() или do_something_important() немного затрудняет анализ). но может попытаться иметь 2 переменных счетчика цикла в разных местах и ​​проверить, отличаются ли они:

int i;
static int ii;

int debug = 0;
for(i = 0, ii = 0; i < buf_end; i++, ii++) {
    if (i != ii) debugBreak();

    do_some_buffer_work();
    if (i != ii) debugBreak();

    if(something_is_true()) {
        if (i != ii) debugBreak();
         do_something_important();
         printf("debug is %i, i is %i", debug++, i);
    }

    if (i != ii) debugBreak();
}

Это может дать вам более близкий контекст, когда дела идут плохо.

0 голосов
/ 03 февраля 2012

Проблема была связана с переоценкой функции побочных эффектов с помощью макроса MAX (a, b).Это было в коде клиента для этой функции.

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