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

#c #visual-studio #segmentation-fault #android-ndk #porting

#c #visual-studio #ошибка сегментации #android-ndk #перенос

Вопрос:

У меня есть проект Visual Studio, который я переношу на Android. Я сталкиваюсь с проблемой ошибки сегментации при вызовах функций, которая напоминает функции ниже:

 char* format1(const char* fmt, ...) {
    char* buf = new char[1030];
    va_list ap;
    va_start(ap, fmt);
    vsprintf(buf, fmt, ap);
    va_end(ap);
    return buf;
}

char* format2(const char* fmt, ...) {
    va_list ap;
    va_start(ap, fmt);
    char* s = format1(fmt, ap);
    va_end(ap);
    return s;
}
  

Вызов функций выглядит следующим образом:

 char* s = format2("%*.*d", 8, 8, 9910153);
  

У меня есть пара запросов относительно вышеизложенного:

Если я пройдусь по коду в gdb для вызова ‘function2’, он покажет: format (fmt = 0x4) Почему это так?

Когда вызывается ‘function1’, gdb показывает: format1 (fmt = 0x15be30 «некоторое случайное значение в памяти») Как получилось, что значение fmt изменилось? Кроме того, в зависимости от значения в fmt второй вызов приводит к ошибке сегментации.

Любая помощь в объяснении приведенного выше поведения была бы весьма признательна.

Комментарии:

1. Просто передайте ap как a va_list или используйте va_arg для его извлечения.

Ответ №1:

format1 принимает переменный набор аргументов, а не a va_list ; вы передаете ему один (нецелочисленный) аргумент, а строка формата ожидает три целочисленных аргумента, поэтому возникает неопределенное поведение.

Это должно быть что-то вроде:

 char* format1(const char* fmt, va_list ap) {
    char* buf = new char[1030];
    vsprintf(buf, fmt, ap);    
    return buf;
}
  

Комментарии:

1. Это не отвечает на вопрос, в котором спрашивалось, почему отладчик сообщает fmt=0x4. Неопределенное поведение vsnprintf не может вызвать это, потому что функция еще не была вызвана.

2. @RobKennedy: Я отвечаю на вопрос в названии: почему существует ошибка сегментации? Я понятия не имею, как именно конкретный отладчик может вести себя при повреждении стека.

3. При входе в format2 (и действительно, даже при входе в format1 ) повреждение стека еще не произошло. Этого не происходит, пока vsnprintf не будет вызвано.

4. @MikeSeymour: Спасибо, я пропустил определение аргумента (случай неаккуратного копирования вставки). Но отображение gdb действительно сбивает с толку, потому что его отображение продолжает отвлекать мое внимание! Любое объяснение отображения gdb? Должен ли я задать это как другой вопрос?