Pergunta

Eu escrevi o seguinte programa C ++

class MyClass {
public:
        int i;
        int j;
        MyClass() {};
};

int main(void)
{
        MyClass inst;
        inst.i = 1;
        inst.j = 2;
}

e eu compilado.

# g++ program.cpp
# ls -l a.out
-rwxr-xr-x  1 root  wheel  4837 Aug  7 20:50 a.out

Então, eu #included o iostream arquivo de cabeçalho no arquivo de origem e eu compilado novamente.

# g++ program.cpp
# ls -l a.out
-rwxr-xr-x  1 root  wheel  6505 Aug  7 20:54 a.out

O tamanho do arquivo, como esperado, foi aumentado.

Eu também escrevi o seguinte programa C

int main(void)
{
    int i = 1;
    int j = 2;
}

e eu compilado

# gcc program.c
# ls -l a.out
-rwxr-xr-x  1 root  wheel  4570 Aug  7 21:01 a.out

Então, eu #included o stdio.h arquivo de cabeçalho e eu compilado novamente

# gcc program.c
# ls -l a.out
-rwxr-xr-x  1 root  wheel  4570 Aug  7 21:04 a.out

Curiosamente, o tamanho dos arquivos executáveis ??permaneceu o mesmo.

Foi útil?

Solução

Ao incluir iostream em seu arquivo de origem, as necessidades do compilador para gerar código de configurar e derrubar o C ++ biblioteca padrão de I / O. Você pode ver isso olhando para a saída do nm, que mostra os símbolos (geralmente funções) em seu arquivo de objeto:

$ nm --demangle test_with_iostream
08049914 d _DYNAMIC
08049a00 d _GLOBAL_OFFSET_TABLE_
08048718 t global constructors keyed to main
0804883c R _IO_stdin_used
         w _Jv_RegisterClasses
080486d8 t __static_initialization_and_destruction_0(int, int)
08048748 W MyClass::MyClass()
         U std::string::size() const@@GLIBCXX_3.4
         U std::string::operator[](unsigned int) const@@GLIBCXX_3.4
         U std::ios_base::Init::Init()@@GLIBCXX_3.4
         U std::ios_base::Init::~Init()@@GLIBCXX_3.4
080485cc t std::__verify_grouping(char const*, unsigned int, std::string const&)
0804874e W unsigned int const& std::min<unsigned int>(unsigned int const&, unsigned int const&)
08049a3c b std::__ioinit
08049904 d __CTOR_END__
... (remaining output snipped) ...

(--demangle leva o ++ nomes de função "mutilados" C por pelo compilador e produz nomes mais significativos. A primeira coluna é o endereço, se a função está incluído no executável. A segunda coluna é o tipo. "T" é . código no segmento de "texto" "U" são símbolos ligados em de outros lugares;. neste caso, a partir da biblioteca compartilhada C ++)

Compare isso com as funções geradas a partir de seu arquivo de origem sem incluir iostream:

$ nm --demangle test_without_iostream
08049508 d _DYNAMIC
080495f4 d _GLOBAL_OFFSET_TABLE_
080484ec R _IO_stdin_used
         w _Jv_RegisterClasses
0804841c W MyClass::MyClass()
080494f8 d __CTOR_END__
... (remaining output snipped) ...

Quando o arquivo de origem incluído iostream, o compilador gerou várias funções não presentes sem iostream.

Quando o arquivo de origem inclui apenas stdio.h, o binário gerado é semelhante ao teste sem iostream, já que a biblioteca C padrão I / O não precisa de qualquer inicialização extra acima e além do que já está acontecendo na biblioteca C dinâmico. Você pode ver isso olhando para a saída nm, que é idêntico.

Em geral, porém, tentando informações intuir sobre a quantidade de código gerado por um arquivo de origem específica com base no tamanho do executável não vai ser significativo; Há muita coisa que poderia mudar, e coisas simples como a localização do arquivo de origem pode alterar o binário se o compilador inclui informações de depuração.

Você também pode encontrar objdump útil para bisbilhotar o conteúdo de seus executáveis.

Outras dicas

Os arquivos de cabeçalho são tipicamente apenas declarações e não resultam diretamente em código de máquina que está sendo gerado. O ligador é inteligente o suficiente para não puxar em funções não utilizados da CRT, por isso, apenas incluindo stdio.h sem usar qualquer das suas funções não resultaria em mais código em seu executável.

EDIT:. Eles podem incluir funções inline, classes e assim por diante, que não incluem código, mas aqueles não deve resultar em um aumento em seu tamanho executável até que eles são realmente utilizados

iostream inclui código. stdio.h não.

Mais especificamente, as seguintes definições em iostream (há mais de listado, e variam de acordo com o compilador) de referência objetos criados na biblioteca padrão, que são então ligados em seu código:

extern istream &cin;
extern ostream &cout;
extern ostream &cerr;
extern ostream &clog;

Existem algumas inicializações estáticas em iostream, enquanto em stdio.h existem apenas funções e eles definições. Portanto incluindo iostream irá produzir executável de maior tamanho.

Geralmente falando, arquivos de cabeçalho conter apenas informações para o compilador, não código real. Por exemplo:

struct foo {
  int x;
};

definições estrutura como que muitas vezes aparecem em cabeçalhos, mas eles realmente não causa código a ser gerado, como eles só dar a informação compilador sobre como lidar com 'foo', deveria vê-lo mais tarde. Se não ver foo, a informação é perdida quando os compilação acabamentos.

Na verdade, ter qualquer coisa que faz gerar código geralmente produzem um erro. Por exemplo:

void foo() {
  printf("bar!\n");
}

Se isto está em um cabeçalho, e é incluído em dois arquivos .c, a função foo() será gerada duas vezes . Isto irá causar um erro no link. É possível evitar o erro se você tem uma forte razão para fazê-lo, mas o código geralmente gerando realmente nos cabeçalhos é evitado, se possível.

Note que uma exceção aqui é membros embutidos em C ++. Por exemplo:

class Foo {
  void bar() { /* ... */ }
};

Tecnicamente bar falar () é gerado em cada arquivo que inclui esse código. O compilador faz vários truques para evitar o erro (de ligação fraca, etc). Isso pode realmente aumentar o tamanho do executável, e é provavelmente o que você viu com <iostream>.

O cabeçalho <iostream> vem com um par de objetos ', std :: cin, 'std::cout, std::cerr e std::clog. Estes são instâncias de classes que têm construtores não-triviais e destruidores. Estes são de código e tem que estar ligado. Isto é o que aumenta o tamanho do executável.

AFAIK, <cstdio> não vem com código, é por isso que não há nenhum aumento no tamanho do executável.

arquivo iostream declarou alguns objetos globais:

std :: cout, std :: cerr, std :: cin que são do tipo ostream.

Em seguida, o compilador irá trazer essa classe e compilá-lo para a direita em seu binário final, adicionando tanto ao seu tamanho.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top