Apakah ada kasus, di mana yang hilang #include
akan merusak perangkat lunak saat runtime, sementara build masih berjalan?
Dengan kata lain, mungkinkah itu
#include "some/code.h"
complexLogic();
cleverAlgorithms();
dan
complexLogic();
cleverAlgorithms();
akan sama-sama membangun dengan sukses, tetapi berperilaku berbeda?
#include
d.#include <vld.h>
dalam posisi strategis dalam kode Anda. Menghapus atau menambahkan header VLD itu tidak "merusak" program, tetapi itu mempengaruhi perilaku runtime secara signifikan. Saya telah melihat VLD memperlambat program hingga tidak dapat digunakan lagi.Jawaban:
Ya, sangat mungkin. Saya yakin ada banyak cara, tetapi anggaplah file include berisi definisi variabel global yang disebut konstruktor. Dalam kasus pertama, konstruktor akan mengeksekusi, dan yang kedua tidak.
Menempatkan definisi variabel global dalam file header adalah gaya yang buruk, tetapi itu mungkin.
sumber
<iostream>
di perpustakaan standar tidak tepat ini; jika ada unit terjemahan termasuk<iostream>
makastd::ios_base::Init
objek statis akan dibangun pada awal program, menginisialisasi aliran karakterstd::cout
dll, jika tidak maka tidak akan.Ya itu mungkin.
Segala sesuatu yang berkaitan
#include
terjadi pada waktu kompilasi. Tetapi kompilasi waktu hal-hal dapat mengubah perilaku saat runtime, tentu saja:some/code.h
:kemudian
Dengan
#include
, resolusi kelebihan menemukan yang lebih tepatfoo(int)
dan karenanya mencetak1
daripada2
. Juga, sejakFOO
didefinisikan, ia juga mencetakFOO
.Itu hanya dua contoh (tidak berhubungan) yang langsung muncul di benak saya, dan saya yakin ada banyak lagi.
sumber
Hanya untuk menunjukkan kasus sepele, arahan precompiler:
Lalu
Ini patologis, mungkin, tapi saya punya kasus terkait terjadi:
Terlihat tidak berbahaya. Mencoba menelepon
std::max
. Namun, windows.h mendefinisikan max menjadiJika ini
std::max
, ini akan menjadi panggilan fungsi normal yang mengevaluasi f () sekali dan g () sekali. Tetapi dengan windows.h di sana, sekarang mengevaluasi f () atau g () dua kali: sekali selama perbandingan dan sekali untuk mendapatkan nilai kembali. Jika f () atau g () tidak idempoten, ini dapat menyebabkan masalah. Misalnya, jika salah satu dari mereka kebetulan adalah penghitung yang mengembalikan nomor yang berbeda setiap kali ....sumber
using namespace std;
dan menggunakanstd::max(f(),g());
, kompiler akan menangkap masalah (dengan pesan yang tidak jelas, tetapi setidaknya menunjuk ke situs panggilan).Mungkin saja ada spesialisasi template yang hilang.
sumber
Ketidakcocokan biner, mengakses anggota atau bahkan lebih buruk, memanggil fungsi dari kelas yang salah:
Sebuah fungsi menggunakannya, dan tidak apa-apa:
Membawa versi lain dari kelas:
Menggunakan fungsi di main, definisi kedua mengubah definisi kelas. Ini menyebabkan ketidakcocokan biner dan hanya crash saat runtime. Dan perbaiki masalah dengan menghapus menyertakan pertama di main.cpp:
Tidak ada varian yang menghasilkan kesalahan waktu kompilasi atau tautan.
Situasi sebaliknya, menambahkan sertakan perbaikan kerusakan:
Situasi ini bahkan jauh lebih sulit ketika memperbaiki bug di versi program lama, atau menggunakan perpustakaan eksternal / dll / objek bersama. Itu sebabnya kadang-kadang harus diikuti aturan kompatibilitas mundur biner.
sumber
Saya ingin menunjukkan bahwa masalahnya juga ada di C.
Anda dapat memberi tahu kompiler bahwa suatu fungsi menggunakan beberapa konvensi pemanggilan. Jika tidak, kompiler harus menebak bahwa ia menggunakan yang default, tidak seperti di C ++ di mana kompiler dapat menolak untuk mengkompilasinya.
Sebagai contoh,
main.c
foo.c
Di Linux pada x86-64, output saya adalah
Jika Anda menghilangkan prototipe di sini, kompilator mengasumsikan Anda memilikinya
Dan konvensi untuk daftar argumen yang tidak ditentukan mensyaratkan bahwa
float
harus dikonversidouble
agar dapat disahkan. Jadi walaupun saya berikan1.0f
, kompiler mengkonversinya1.0d
untuk meneruskannyafoo
. Dan menurut System V Application Binary Interface, Tambahan Prosesor Arsitektur AMD64,double
akan dilewatkan dalam 64 bit paling tidak signifikanxmm0
. Tetapifoo
mengharapkan float, dan membacanya dari 32 bit paling tidak signifikanxmm0
, dan mendapat 0.sumber