缺少#include 是否有可能在运行时破坏程序?

Ant*_*i_M 32 c++

是否有任何情况下,缺少 a#include会在运行时破坏软件,而构建仍在进行中?

换句话说,有没有可能

#include "some/code.h"
complexLogic();
cleverAlgorithms();
Run Code Online (Sandbox Code Playgroud)

complexLogic();
cleverAlgorithms();
Run Code Online (Sandbox Code Playgroud)

两者都会成功构建,但行为不同吗?

joh*_*ohn 41

是的,这是完全可能的。我确信有很多方法,但假设包含文件包含一个称为构造函数的全局变量定义。在第一种情况下,构造函数会执行,而在第二种情况下不会。

将全局变量定义放在头文件中是一种糟糕的风格,但这是可能的。


pas*_*sbi 34

是的,这是可能的。

#includes有关的一切都发生在编译时。但是编译时的事情可以在运行时改变行为,当然:

some/code.h

#define FOO
int foo(int a) { return 1; }
Run Code Online (Sandbox Code Playgroud)

然后

#include <iostream>
int foo(float a) { return 2; }

#include "some/code.h"  // Remove that line

int main() {
  std::cout << foo(1) << std::endl;
  #ifdef FOO
    std::cout << "FOO" std::endl;
  #endif
}
Run Code Online (Sandbox Code Playgroud)

使用#include,重载解析会找到更合适的foo(int),因此打印1而不是2. 此外,由于FOO已定义,它还会额外打印 FOO.

这只是我立即想到的两个(不相关的)例子,我相信还有更多。


Cor*_*ica 15

只是为了指出微不足道的情况,预编译器指令:

// main.cpp
#include <iostream>
#include "trouble.h" // comment this out to change behavior

bool doACheck(); // always returns true

int main()
{
    if (doACheck())
        std::cout << "Normal!" << std::endl;
    else
        std::cout << "BAD!" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

进而

// trouble.h
#define doACheck(...) false
Run Code Online (Sandbox Code Playgroud)

这可能是病态的,但我遇到过一个相关的案例:

#include <algorithm>
#include <windows.h> // comment this out to change behavior

using namespace std;

double doThings()
{
    return max(f(), g());
}
Run Code Online (Sandbox Code Playgroud)

看起来无害。尝试调用std::max。但是,windows.h 将 max 定义为

#define max(a, b)  (((a) > (b)) ? (a) : (b))
Run Code Online (Sandbox Code Playgroud)

如果这是std::max,这将是一个普通的函数调用,它计算一次 f() 和一次 g()。但是在 windows.h 中,它现在计算 f() 或 g() 两次:一次是在比较期间,一次是为了获取返回值。如果 f() 或 g() 不是幂等的,这可能会导致问题。例如,如果其中一个恰好是一个每次返回不同数字的计数器......

  • OTOH,如果你摆脱 `using namespace std;` 并使用 `std::max(f(),g());`,编译器会发现这个问题(带有一条晦涩的消息,但至少指向调用站点)。 (4认同)