Есть ли какой-нибудь случай, когда пропадание #include
может сломать программное обеспечение во время выполнения, в то время как сборка все еще проходит?
Другими словами, возможно ли, что
#include "some/code.h"
complexLogic();
cleverAlgorithms();
а также
complexLogic();
cleverAlgorithms();
будут ли оба успешно строить, но вести себя по-разному?
#include
d.#include <vld.h>
в стратегическую позицию в своем коде. Удаление или добавление этого заголовка VLD не «ломает» программу, но существенно влияет на поведение среды выполнения. Я видел, как VLD замедляет программу до такой степени, что она становится непригодной для использования.Ответы:
Да, это вполне возможно. Я уверен, что есть много способов, но предположим, что включаемый файл содержит определение глобальной переменной, которая называется конструктор. В первом случае конструктор будет выполняться, а во втором - нет.
Помещение определения глобальной переменной в заголовочный файл - плохой стиль, но это возможно.
источник
<iostream>
в стандартной библиотеке делает именно это; если какой-либо блок перевода включает в себя,<iostream>
тоstd::ios_base::Init
статический объект будет создан при запуске программы, инициализируя потоки символовstd::cout
и т. д., иначе это не так.Да, это возможно
Все, что касается
#include
s, происходит во время компиляции. Но время компиляции может изменить поведение во время выполнения, конечно:some/code.h
:тогда
С
#include
разрешением перегрузки находит более подходящееfoo(int)
и, следовательно, печатает1
вместо2
. Кроме того, посколькуFOO
он определен, он дополнительно печатаетFOO
.Это всего лишь два (не связанных) примера, которые сразу же пришли мне в голову, и я уверен, что их гораздо больше.
источник
Просто чтобы указать на тривиальный случай, директивы прекомпилятора:
А потом
Возможно, это патология, но у меня был похожий случай:
Выглядит безобидно. Пытается позвонить
std::max
. Тем не менее, windows.h определяет max бытьЕсли бы это было так
std::max
, это был бы обычный вызов функции, который оценивает f () один раз и g () один раз. Но с windows.h теперь он оценивает f () или g () дважды: один раз во время сравнения и один раз, чтобы получить возвращаемое значение. Если f () или g () не были идемпотентами, это может вызвать проблемы. Например, если один из них является счетчиком, который каждый раз возвращает другое число ....источник
using namespace std;
и используетеstd::max(f(),g());
, компилятор поймает проблему (с неясным сообщением, но, по крайней мере, указывая на сайт вызова).Возможно пропустить специализацию шаблона.
источник
Двоичная несовместимость, доступ к члену или, что еще хуже, вызов функции неправильного класса:
Функция использует это, и это нормально:
Ввод в другой версии класса:
Используя функции в основном, второе определение изменяет определение класса. Это приводит к двоичной несовместимости и просто дает сбой во время выполнения. И исправьте проблему, удалив первый файл include в main.cpp:
Ни один из вариантов не генерирует ошибку времени компиляции или ссылки.
И наоборот, добавление include исправляет сбой:
Эти ситуации даже намного сложнее при исправлении ошибки в старой версии программы или при использовании внешнего объекта библиотеки / dll / shared. Вот почему иногда необходимо соблюдать правила двоичной обратной совместимости.
источник
Я хочу отметить, что проблема также существует в C.
Вы можете сказать компилятору, что функция использует некоторые соглашения о вызовах. Если вы этого не сделаете, компилятор должен будет догадаться, что он использует стандартный по умолчанию, в отличие от C ++, где компилятор может отказаться от его компиляции.
Например,
main.c
foo.c
На Linux на x86-64 мой вывод
Если вы опустите здесь прототип, компилятор предполагает, что у вас есть
И соглашение для неопределенных списков аргументов требует,
float
чтобы они были преобразованы вdouble
передаваемые. Поэтому, хотя я и дал1.0f
, компилятор преобразует его в,1.0d
чтобы передатьfoo
. И в соответствии с Дополнением к процессору архитектуры AMD64 двоичного интерфейса приложений System V значенияdouble
передаются в 64 младших значащих битахxmm0
. Ноfoo
ожидает float, и он читает его из 32 младших разрядовxmm0
и получает 0.источник