Estaba probando este simple código C++ en mi computadora portátil Windows 8.1, Intel i7-3517U de 64 bits con GCC 4.8.2.
#include<iostream> using namespace std; int main(int argc, char **argv){ cout << "This test code will simply display any arguments passed." << endl ; for(int i=0; i<argc; i++){ cout << argv[i] << endl ; } return 0 ; }Sorprendentemente, después de compilar, el ejecutable resultó ser de 5905 KB . Por curiosidad, intenté compilar el mismo archivo con la misma versión de GCC en una máquina Linux Fedora 20 de 64 bits. Y el ejecutable ocupaba solo 9 KB .
Después de hacer varias optimizaciones usando g++ -Ox -o fileWithOx.exe file.cpp (x=1,2,3,s), el ejecutable de Windows tenía casi el mismo tamaño. Después de investigar un poco y siguiendo los consejos de MinGW, intenté compilarlos sin depurar la información usando strip g++ -s -o fileWithStrip.exe file.cpp , pero el ejecutable aún tenía 597 KB de tamaño.
Mientras que, por otro lado, el ejecutable de Linux era de solo 6-13 KB para las mismas opciones.
Haciendo algunos experimentos, investigando un poco más y desbordando la pila , estaba casi convencido de que el tamaño gigantesco se debe a que iostream se vincula a muchos otros archivos de encabezado y/o genera algún código de inicialización.
Pero mi duda es que iostream se use tanto en Windows como en Linux. Entonces, ¿por qué tanta diferencia de tamaño? Sé que los ejecutables de Windows y Linux funcionan de manera diferente. Pero 655 veces más grande , ¿no es esto un poco extremo?
La diferencia probablemente no se deba a la compilación sino a la fase de edición de enlace.
Primero intente compilar solo, detenga el comando usando -c , por ejemplo, g++ -c code.cpp en estilo Unix y encuentre las banderas equivalentes en su entorno de Windows. Luego compare los archivos de objetos, deben tener casi el mismo tamaño. Estos archivos de objetos (extensión .o ) solo contienen la traducción de su código al código de máquina. El tamaño podría ser diferente, digamos un factor de 2 o 3 tal vez, pero esto no es relevante.
Lo que sucedió es que el compilador de Windows probablemente usó un enlace estático en alguna biblioteca, por lo que el archivo ejecutable contiene el código de lo que usa en la biblioteca. En Unix, el compilador probablemente vinculó todo dinámicamente, lo que dice que la biblioteca se cargará en tiempo de ejecución y no se incluirá en el ejecutable.
Consulte la documentación de sus compiladores para saber cómo aplicar enlaces estáticos/dinámicos. También debe tener en cuenta que es posible que algún entorno no proporcione ambos tipos de bibliotecas...
Acabo de crear su programa en Windows, usando mingw g ++ versión 4.7.2; solo obtengo 10 kb. No tengo idea de cómo lograste aumentarlo a más de 5 MB. Aquí está la línea cmd y la salida cuando presiono Ctrl-F11 en Code::Blocks 13.12:
mingw32-g++.exe -Wall -fexceptions -O2 -I"C:\Program Files (x86)\CodeBlocks\MinGW\include" -c C:\Users\enhzflep\Documents\code\001-sizeTestDeleteMe\main.cpp - o obj\Release\main.o mingw32-g++.exe -o bin\Release\001-sizeTestDeleteMe.exe obj\Release\main.o -s
El archivo de salida es bin\Release\001-sizeTestDeleteMe.exe con un tamaño de 10,50 KB
Lo siento, no tengo ningún cuadro de Windows en este momento, pero si creo en este artículo,
tal vez fue porque su ejecutable de Windows estaba vinculado estáticamente a libstdc++.a enviado con el conjunto de compiladores Mingw, mientras que la versión de Linux estaba vinculada dinámicamente a algo como /usr/lib64/libstdc++.so.6 . Este último es uno de los componentes estándar de la mayoría de las distribuciones de Linux y el vinculador dinámico puede buscarlo, por lo que Linux g++ puede confiar en él de manera segura. Pero el primero no lo es, así que tal vez Mingw g++ decidió emplear enlaces estáticos.
El siguiente artículo (sobre Mingw GCC 4.4) dice que puede decirle a Mingw g++ que vincule dinámicamente libstdc++.dll con la opción de línea cmd -lstdc++_s
Solo para su información, así es como un pequeño exe de C++ se vincula dinámicamente a libstdc++.so.6 en mi caja de Debian:
$ ldd valueInit linux-vdso.so.1 (0x00007fff641fe000) libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f20618e2000) libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f20615e4000) libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f20613cd000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f2061021000) /lib64/ld-linux-x86-64.so.2 (0x00007f2061c12000) $ LANG=C ls -lH /usr/lib/x86_64-linux-gnu/libstdc++.so.6 -rw-r--r-- 1 root root 953K Jan 6 12:24 /usr/lib/x86_64-linux-gnu/libstdc++.so.6 libstdc++.so.6 contiene definiciones de muchas funciones iostream , etc.
$ readelf -sW /usr/lib/x86_64-linux-gnu/libstdc++.so.6 | grep stream | c++filt | head -3 135: 0000000000084360 51 FUNC WEAK DEFAULT 12 std::money_get<char, std::istreambuf_iterator<char, std::char_traits<char> > >::get(std::istreambuf_iterator<char, std::char_traits<char> >, std::istreambuf_iterator<char, std::char_traits<char> >, bool, std::ios_base&, std::_Ios_Iostate&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&) const@@GLIBCXX_3.4 137: 00000000002e8ff0 24 OBJECT WEAK DEFAULT 23 typeinfo for std::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >@@GLIBCXX_3.4 138: 000000000009f1d0 15 FUNC WEAK DEFAULT 12 std::num_put<wchar_t, std::ostreambuf_iterator<wchar_t, std::char_traits<wchar_t> > >::put(std::ostreambuf_iterator<wchar_t, std::char_traits<wchar_t> >, std::ios_base&, wchar_t, void const*) const@@GLIBCXX_3.4