当我在 Docker 中运行用 G ++ 编译的程序时的不同行为

Different behavior when I running a program compiled with G ++ in Docker

本文关键字:程序 编译 Docker 运行      更新时间:2023-10-16

如果可执行文件在 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 && apt-get install -y 
   libssl-dev
COPY fast/ /usr/local/
ENTRYPOINT ["usr/local/FastCompile"]

$docker 构建 -t 快速编译 .

$docker运行快速编译

BEFORE SPRINTF 003395

AFTER SPRINTF P

如果我删除 -O 并使用以下命令重新编译:

g++ -o FastCompile FastCompile.c -DNDEBUG 

该行为在 Docker 中是正确的。

所以这是 Docker 问题吗?还是预期行为?

您的代码具有未定义的行为。

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));