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

时间:2019-04-09 14:42:35

标签: c++ docker g++ compiler-optimization

如果可执行文件在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 %s\n\n\n", cAux2);
    sprintf(cAux2, "%s%c", cAux2, (nRest+65));
    printf("AFTER SPRINTF %s\n\n\n", 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 build -t fastcompile。

$ docker运行fastcompile

BEFORE SPRINTF 003395


AFTER SPRINTF P

如果我删除-Os并重新编译为:

g++ -o FastCompile FastCompile.c -DNDEBUG 

该行为在Docker内部是正确的。

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

1 个答案:

答案 0 :(得分:5)

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

sprintf(cAux2, "%s%c", cAux2, (nRest+65));

读取和写入相同的对象。要解决此问题,您可以在调用中使用cOrd,这样就不会从缓冲区读取数据。看起来像

sprintf(cAux2, "%s%c", cOrd, (nRest+65));

还请注意,(nRest+65)会给您int,而不是格式说明符指出的char。这也是未定义的行为。您需要将其转换为char进行修复,例如

sprintf(cAux2, "%s%c", cOrd, char(nRest+65));