Hungry Mind , Blog about everything in IT - C#, Java, C++, .NET, Windows, WinAPI, ...

Precompiled Headers Explained

Почти все разработчики, использующие Visual C++, сталкиваются с файлом stdafx.h, в который можно положить много-много различных директив препроцессора. И так мало понимают, зачем это нужно и как с этим работать...

Precompiled Header

Вы, наверное, слышали о понятии Precompiled Header. Precompiled Header - это механизм, позволяющий компиляторам сократить время сборки приложения путем прекомпиляции редко меняющихся файлов исходного кода приложения. В первую очередь - это библиотечный код, точнее заголовочные файлы.

Рассмотрим программу Hello World:

#include <tchar.h>
#include <iostream>

int _tmain(int argc, _TCHAR* argv[]) {
    std::cout << "Hello World!" << std::endl;
    return 0;
}

А теперь внимание: после обработки этого файла прекомпилятором, его размер возрастает до 996 килобайт! Я повторюсь: 996 килобайт, из которых 854 составляют полезный код (остальное - комментарии), а размер рабочего кода программы - аж 142 байта. Похоже, для компиляции нашего простейшего cpp-файла компилятору прийдется изрядно потрудиться. Причем над каждым cpp-файлом проекта.

Естественно, лучше предварительно обработать неизменящиеся куски кода, превратив их в удобный и быстрый формат для последующей обработки в составе исходного кода приложения. Компиляторы Visual C++ и GCC поддерживают такую обработку и она носит имя Precompiled Header.

Использование Precompiled Header в Visual C++

Мастер создания проекта Visual C++ предлагает свои услуги по настройке Precompiled Header. В простейшем случае, среда дает разработчику возможность выбора - использовать этот механизм или нет. В большинстве случаев использование Precompiled Header настраивается автоматически.

Анализ настроек Precompiled Header мастеров Visual C++

Что же мы получаем при автоматической настройке Precompiled Header средой разработки Visual Studio?

  1. Заголовочный файл stdafx.h

    В этом файле содержатся, как правило, только директивы препроцессора, подключающие внешние заголовочные файлы.

  2. cpp-файл stdafx.cpp

    Состоит из единственной директивы #include "stdafx.h" и используется для генерации Precompiled Header. Следующая картинка демонстрирует свойства файла stdafx.cpp, раздел C/C++, подраздел Precompiled Headers:stdafx.cpp Property Pages

  3. Каждый cpp-файл проекта, использующий Precompiled Header, обязан включать этот заголовочный файл соответствующей директивой #include "stdafx.h"

    При этом компилятор игнорирует любой текст до момента включения stdafx.h! А в случае его отсутствия - выдает ошибку fatal error C1010: unexpected end of file while looking for precompiled header. Did you forget to add '#include "stdafx.h"' to your source?

  4. Использование Precompiled Header установлено на уровне cpp-файлов всего проекта, как показано на картинке:

    Project Property Pages

Настройка Precompiled Header вручную

Опираясь на вышенаписанное, последовательность действий простая:

  1. Создать файл CommonIncludes.h
  2. Создать файл CommonIncludes.cpp и добавить туда одну строчку - #include "CommonIncludes.h"
  3. Поменять нужные настройки Precompiled Headers в свойствах файла CommonIncludes.cpp
  4. Поменять настройки Precompiled Headers на уровне проекта или на уровне отдельных cpp-файлов
  5. Добавить #include "CommonIncludes.h" в начало соответствующих cpp-файлов исходного кода

Продвинутое использование Precompiled Header

Как правило, в stdafx.h, созданный визардом, лепят все, что можно влепить. В результате в каждый cpp-файл включается совершенно ненужный ему контент! Поэтому, логично включать в stdafx.h только наиболее используемые заголовочные файлы.

Директивы прекомпилятора в stdafx.h распостраняются одинаковым образом на все cpp-файлы, включающие данный заголовочный файл. Бывает, необходимо настроить поведение библиотеки (в рамках отдельного cpp-файла или группы таких файлов) путем определения каких-то символов перед включением соответствующего заголовочного файла. Первое, что приходит на ум, - определить эти символы в cpp-файле и еще раз включить заголовочный файо библиотеки. Но, нет, я же писал, что компилятор игнорирует любой исходный код до строчки #include "stdafx.h"! Соответственно, повторное включение заголовочных файлов будет просто проигнорировано. Получается, нужно удалять включения заголовочных файлов библиотек из stdafx.h и добавлять их в каждый отдельный cpp-файл.

Также, проект не ограничен одним Precompiled Header! Вполне можно содзать пару файлов Subsystem1Includes.h, Subsystem1Includes.cpp, отвечающих за отдельный Precompiled Header в рамках некоторой группы файлов исходного кода.

Компилятор Visual C++ имеет ограничение на размер pch-файла. На практике это выглядит следующим образом:

error C3859: virtual memory range for PCH exceeded; please recompile with a command line option of '-Zm130' or greater
fatal error C1076: compiler limit : internal heap limit reached; use /Zm to specify a higher limit

В таком случае спасет опция компилятора /Zm: /Zm compiler option

20 коммент.:

Анонимный комментирует...

Спасибо большое! Очень помогло разобраться с проблемой компиляции с использованием Precompiled Headers.

Анонимный комментирует...

Благодарю, замечательная статья. То, что надо, и кратко.

Анонимный комментирует...

Помогли исправить ошибку и просветили. Спасибо

Анонимный комментирует...

Огромное человеческое спасибо! Сколько времени с C++ работаю, а так с Precompiled Headers и не удосуживался разобраться. А тут все четко, коротко и понятно. Всего Вам хорошего и еще раз спасибо за статью! =)

Анонимный комментирует...

Я буду лаконичен-спасибо

Анонимный комментирует...

Статья хорошая, но не "предлОгает", а "предлАгает".
:)

Анонимный комментирует...

не очень понятное объяснение для "чайника", но спасибо за попытку :)

Анонимный комментирует...

спасибо большое - сам бы никогда не разобрался

pethead комментирует...

настроил эти хедеры, раза в 3 вроде убыстрилась сборка.
а ключ /MP не пробовали?

Анонимный комментирует...

Спасибо! Опция /Zm очень пригодилась.

Анонимный комментирует...

Кому после этого непонятно - учите "Албанский". А автору спасибо 1 минута и в голове всё стало на свои места.

Анонимный комментирует...

ну громаднейшие спасибо!!!!!!!!!!!!!!!!а то мучался долго!

Алексей комментирует...

К сожалению, не все компиляторы это поддерживают, но спасибо мелкомягким и на этом!

Анонимный комментирует...

прочитал, сделал, радуюсь
спасибо, коротко и ясно!)

Анонимный комментирует...

I've been surfing on-line more than three hours these days, yet I by no means discovered any attention-grabbing article like yours. It is pretty price sufficient for me. In my view, if all webmasters and bloggers made excellent content as you probably did, the internet might be much more helpful than ever before.

Review my page: free movies online

Анонимный комментирует...

Hey would you mind stating which blog platform you're working with? I'm looking to start my
own blog in the near future but I'm having a difficult time selecting between BlogEngine/Wordpress/B2evolution and Drupal. The reason I ask is because your design seems different then most blogs and I'm looking for something
unique. P.S Apologies for being off-topic but
I had to ask!

my website: freepressreleasenow.com

Анонимный комментирует...

Greetings! I've been following your website for a long time now and finally got the bravery to go ahead and give you a shout out from Lubbock Tx! Just wanted to say keep up the good work!

Take a look at my site; tv online
My page: tvlinks

Анонимный комментирует...

I am curious to find out what blog platform you're working with? I'm having some small security issues with
my latest blog and I'd like to find something more secure. Do you have any solutions?

Also visit my page rideanything.com
my webpage > free tv online

Анонимный комментирует...

Thank you for every other informative site.
The place else could I am getting that kind of info written in such a perfect way?
I've a mission that I'm just now running on, and I've been at the glance out for such info.

Feel free to visit my blog tvlinks

Andrey Karpov комментирует...

Для новичков про stdafx.h - http://www.viva64.com/ru/b/0265/

Отправить комментарий

Copyright 2007-2011 Chabster