#c #docker #g #compiler-optimization
#c #docker #g #оптимизация компилятора
Вопрос:
Поведение исполняемого файла отличается, если он запускается внутри docker или на хосте. Но это происходит только тогда, когда мы меняем уровень оптимизации G .
Компилятор: g (Ubuntu 7.3.0-27ubuntu1 ~ 18.04) 7.3.0
Я пытаюсь выполнить следующий код:
#include <cstdio>
#include <cstring>
int main()
{
int nOrd =3395;
char cOrd[] = "003395";
char cAux2[256];
strcpy(cAux2, cOrd);
int nRest = nOrd % 26;
printf("BEFORE SPRINTF %snnn", cAux2);
sprintf(cAux2, "%s%c", cAux2, (nRest 65));
printf("AFTER SPRINTF %snnn", cAux2);
return 0;
}
Если я скомпилирую с:
g -o FastCompile FastCompile.c -DNDEBUG -Os
И я запускаю на хосте. Результат соответствует ожидаемому:
BEFORE SPRINTF 003395
AFTER SPRINTF 003395P
Если я создаю образ с этим исполняемым файлом и запускаю внутри docker, у меня есть:
Версия Docker 18.09.4, сборка d14af54266
Dockerfile:
FROM debian
RUN apt-get update amp;amp; apt-get install -y
libssl-dev
COPY fast/ /usr/local/
ENTRYPOINT ["usr/local/FastCompile"]
Быстрая компиляция $docker build -t.
$docker запустить fastcompile
BEFORE SPRINTF 003395
AFTER SPRINTF P
Если я удалю -Os и повторно скомпилирую с:
g -o FastCompile FastCompile.c -DNDEBUG
Поведение внутри Docker правильное.
Итак, это проблема Docker? Или это ожидаемое поведение?
Ответ №1:
Ваш код имеет неопределенное поведение.
sprintf(cAux2, "%s%c", cAux2, (nRest 65));
считывает данные из одного и того же объекта и записывает в него. Чтобы исправить это, вы можете использовать cOrd
в вызове, чтобы вы не читали из своего буфера. Это выглядело бы как
sprintf(cAux2, "%s%c", cOrd, (nRest 65));
Также обратите внимание, что это (nRest 65)
дает вам int
, а не char
, как указано в спецификаторе формата, должно быть. Это также неопределенное поведение. Вам нужно преобразовать ее в символ, чтобы исправить это следующим образом
sprintf(cAux2, "%s%c", cOrd, char(nRest 65));
Комментарии:
1. Нет ли второго неопределенного поведения, поскольку в строке формата указано,
%c
но(nRest 65)
этоint
?2. Этот фрагмент кода взят из старого кода, написанного на Visual C 6. Я переопределю его, чтобы удалить неопределенное поведение. Спасибо