Форум программистов, компьютерный форум CyberForum.ru

Почему глобальный объект, объявленный до main, конструируется в ней? - C++

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 17, средняя оценка - 4.82
kravam
быдлокодер
 Аватар для kravam
1512 / 872 / 44
Регистрация: 04.06.2008
Сообщений: 5,271
13.09.2011, 17:16     Почему глобальный объект, объявленный до main, конструируется в ней? #1
Всё просто, имеем код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <windows.h>
#include <stdio.h>
using namespace std;
 
class x {
 public:
 x () { 
  printf ("konstruktor\n");     
 }
};
x x_;
 
int main() {
 printf ("%x\n", main);
 getchar();
 return 0;
}
запускаем, видим:
C++
1
2
konstruktor
401290
последнее значение адрес main, у каждого своё.
Так, открываем прогу в отладчике OllyDbg, стоим на точке входа (у всех своя, у меня) 401220, ставим бряк на 401290, на main, запускаем. Видим, что бряк сработал, но конструктор не вызвался! Чуть пониже в окне дизассембра видим вызов printf с аргументом "konstruktor", то есть объект конструируется в main. Как такое может быть? Компилятор g++. Спасибо, кто откликнется.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
13.09.2011, 17:16     Почему глобальный объект, объявленный до main, конструируется в ней?
Посмотрите здесь:

C++ _tmain(...) вместо main(...) Почему?
Почему ругается на не объявленный идентификатор C++
C++ Динамический глобальный объект.
Глобальный объект C++
C++ Почему не хочет возвращать main() ?
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Mr.X
Эксперт С++
 Аватар для Mr.X
2805 / 1581 / 248
Регистрация: 03.05.2010
Сообщений: 3,684
13.09.2011, 17:35     Почему глобальный объект, объявленный до main, конструируется в ней? #2
Перед началом программы инициализируются только объекты POD-типов, а ваш класс имеет конструктор, определенный пользователем, поэтому POD-классом не является.
Сыроежка
Заблокирован
13.09.2011, 17:50     Почему глобальный объект, объявленный до main, конструируется в ней? #3
Все переменные со статической памятью инициализируются нулем до выполнения программы. При этом глобальные объекты классов повторно инициализируются конструктором до точки входа main, то есть до того, как main получит управление. Тем не менее все функции вашей программы находятся в одном исполняемом модуле.
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16830 / 5251 / 322
Регистрация: 30.03.2009
Сообщений: 14,144
Записей в блоге: 26
13.09.2011, 17:59     Почему глобальный объект, объявленный до main, конструируется в ней? #4
Цитата Сообщение от Сыроежка Посмотреть сообщение
то есть до того, как main получит управление
Более правильным было бы сказать "до того, как исполнится первый оператор main'а". Потому как некоторые компиляторы вызов глобальных конструкторов встраивают в самое начало main'а

Цитата Сообщение от kravam Посмотреть сообщение
Так, открываем прогу в отладчике OllyDbg, стоим на точке входа
Что в твоём понятии есть "точка входа"? Могу тебе сказать, что это точно НЕ функция main. По честному брекпоинт надо ставить на первый оператор main'а
Сыроежка
Заблокирован
13.09.2011, 18:05     Почему глобальный объект, объявленный до main, конструируется в ней? #5
Цитата Сообщение от Evg Посмотреть сообщение
Более правильным было бы сказать "до того, как исполнится первый оператор main'а". Потому как некоторые компиляторы вызов глобальных конструкторов встраивают в самое начало main'а
Нет, это будет неправильно, так как это не соответсвует букве стандарта. Это разработчики компиляторов делают на свой страх и риск!

Цитата Сообщение от Evg Посмотреть сообщение
Что в твоём понятии есть "точка входа"? Могу тебе сказать, что это точно НЕ функция main. По честному брекпоинт надо ставить на первый оператор main'а
Не только по-моему, но и в соответствии с языками С и С++ точкой входа функции является адрес этой функции, который устанавливается при редактировании связей и формировании загрузочного модуля.
kravam
быдлокодер
 Аватар для kravam
1512 / 872 / 44
Регистрация: 04.06.2008
Сообщений: 5,271
13.09.2011, 18:15  [ТС]     Почему глобальный объект, объявленный до main, конструируется в ней? #6
Цитата Сообщение от Evg Посмотреть сообщение
Что в твоём понятии есть "точка входа"? Могу тебе сказать, что это точно НЕ функция main. По честному брекпоинт надо ставить на первый оператор main'а
А я чё делаю?
Читаем внимательно, сперва ищем адрес maina, потом в отладчике стоя в точке входа, ставим бряк на первый оператор mainф, это у меня 401290

Точка входа в данном контексте это то, на чём остановился OllyDbg после того, как в нём была открыта прога. Там даже надпись по английски: стоим на точке входа.

...И да, вообще в моём понимании точка входа это адрес, RVA которого находится в поле IMAGE_OPTIONAL_HEADER. AddressOfEntryPoint опциональном заголовка PE файла. И OLlyDbg со мной согласен- он там и останавливается.

Добавлено через 1 минуту
Сыроежка, имеется ввиду не точка входа в функцию, какую-либо, но точка входа в исполняемый файл. Немного корявое определение, но именно о нём и идёт речь.

Добавлено через 1 минуту
Цитата Сообщение от Сыроежка Посмотреть сообщение
Тем не менее все функции вашей программы находятся в одном исполняемом модуле.
Сыроежка, я не понял, у меня шанс есть какой-нибудь? Мне надо функции по разным исполняемым модулям разнести или как?
grizlik78
Эксперт С++
 Аватар для grizlik78
1884 / 1416 / 102
Регистрация: 29.05.2011
Сообщений: 2,961
13.09.2011, 18:16     Почему глобальный объект, объявленный до main, конструируется в ней? #7
Цитата Сообщение от Сыроежка Посмотреть сообщение
Не только по-моему, но и в соответствии с языками С и С++ точкой входа функции является адрес этой функции, который устанавливается при редактировании связей и формировании загрузочного модуля.
А какая, по большому счёту разница, если стандарт С++ не разрешает получение адреса функции main()? Правда как-раз именно GCC это ограничение не выполняет и разрешает рекурсивный вызов функции main() в C++.
Сыроежка
Заблокирован
13.09.2011, 18:18     Почему глобальный объект, объявленный до main, конструируется в ней? #8
Цитата Сообщение от kravam Посмотреть сообщение
А я чё делаю?
Читаем внимательно, сперва ищем адрес maina, потом в отладчике стоя в точке входа, ставим бряк на первый оператор mainф, это у меня 401290

Точка входа в данном контексте это то, на чём остановился OllyDbg после того, как в нём была открыта прога. Там даже надпись по английски: стоим на точке входа.

...И да, вообще в моём понимании точка входа это адрес, RVA которого находится в поле IMAGE_OPTIONAL_HEADER. AddressOfEntryPoint опциональном заголовка PE файла. И OLlyDbg со мной согласен- он там и останавливается.

Добавлено через 1 минуту
Сыроежка, имеется ввиду не точка входа в функцию, какую-либо, но точка входа в исполняемый файл. Немного корявое определение, но именно о нём и идёт речь.
Точка входа у модуля одна, если только конечно это не модуль, написанный на ассемблере, где можно самостоятельно устанавливать несколько точек входа. Кроме того, когда вы устанавливаете свой отладчик на точке входа main, он пропускает инициализирующий код, то есть не обязательно сам этот код, который может находиться в любом месте модуля, а его вызов. То есть его вызов происходит до точки входа в main, ко крайней мере должно быть так.
grizlik78
Эксперт С++
 Аватар для grizlik78
1884 / 1416 / 102
Регистрация: 29.05.2011
Сообщений: 2,961
13.09.2011, 18:19     Почему глобальный объект, объявленный до main, конструируется в ней? #9
Цитата Сообщение от kravam Посмотреть сообщение
Сыроежка, я не понял, у меня шанс есть какой-нибудь?
А можешь сказать зачем тебе это? Мне просто интересно, какая разница, в каком месте вызывается конструктор.
Сыроежка
Заблокирован
13.09.2011, 18:19     Почему глобальный объект, объявленный до main, конструируется в ней? #10
Цитата Сообщение от grizlik78 Посмотреть сообщение
А какая, по большому счёту разница, если стандарт С++ не разрешает получение адреса функции main()? Правда как-раз именно GCC это ограничение не выполняет и разрешает рекурсивный вызов функции main() в C++.
Вы путаете получение этого адреса внутри кода main, и тем, что отладчик знает этот адрес, так как он владеет всем модулем, а не только начиная с main, как это имеет место в отношении пользовательского кода.
grizlik78
Эксперт С++
 Аватар для grizlik78
1884 / 1416 / 102
Регистрация: 29.05.2011
Сообщений: 2,961
13.09.2011, 18:22     Почему глобальный объект, объявленный до main, конструируется в ней? #11
Цитата Сообщение от Сыроежка Посмотреть сообщение
Вы рутаете получение этого адреса внутри кода main, и тем, что отладчик знает этот адрес, так как он владеет всем модулем, а не только начиная с main, как это имеет место в отношении пользовательского кода.
Я не путаю. Отладчик меня вообще не интересует. Я спрашиваю с точки зрения разработчика программы, а не с точки зрения разработчика компилятора или отладчика. Так какая разница, в каком месте вызывается конструктор, если он в любом случае вызывается до пользовательского кода из main()?
kravam
быдлокодер
 Аватар для kravam
1512 / 872 / 44
Регистрация: 04.06.2008
Сообщений: 5,271
13.09.2011, 18:27  [ТС]     Почему глобальный объект, объявленный до main, конструируется в ней? #12
Я нашёл противоречие между теорией, которая гласит, что если объект глобальный относительно какой-нибудь функции, то вне её он и должен конструироваться и практикой. Хочу Это противоречие разрешить. Просто стараюсь добросовестно учиться только и всего.
Сыроежка
Заблокирован
13.09.2011, 18:28     Почему глобальный объект, объявленный до main, конструируется в ней? #13
Цитата Сообщение от grizlik78 Посмотреть сообщение
Я не путаю. Отладчик меня вообще не интересует. Я спрашиваю с точки зрения разработчика программы, а не с точки зрения разработчика компилятора или отладчика. Так какая разница, в каком месте вызывается конструктор, если он в любом случае вызывается до пользовательского кода из main()?
Возможно, с практической точки зрения никакой, но тем не менее стандарт говорит по этому поводу вполне определенно. Поэтому я и написал, что разработчики компиляторов делают это на свой страх и риск.
grizlik78
Эксперт С++
 Аватар для grizlik78
1884 / 1416 / 102
Регистрация: 29.05.2011
Сообщений: 2,961
13.09.2011, 18:29     Почему глобальный объект, объявленный до main, конструируется в ней? #14
Что касается отладчика, то на мой взгляд (это лишь моё мнение, да) отладчик останавливается до вызова конструктора не по ошибке, а как раз чтобы была возможность отследить, какие объекты инициализируются до начала программы. Но я не знаю этого наверняка.

Цитата Сообщение от kravam Посмотреть сообщение
Я нашёл противоречие между теорией, которая гласит, что если объект глобальный относительно какой-нибудь функции, то вне её он и должен конструироваться и практикой. Хочу Это противоречие разрешить. Просто стараюсь добросовестно учиться только и всего.
Отладчик не обязательно отражает истинное положение вещей. В ассемблерный код посмотреть надёжнее всего. Пожалуй, пойду посмотрю.
Сыроежка
Заблокирован
13.09.2011, 18:29     Почему глобальный объект, объявленный до main, конструируется в ней? #15
Цитата Сообщение от kravam Посмотреть сообщение
Я нашёл противоречие между теорией, которая гласит, что если объект глобальный относительно какой-нибудь функции, то вне её он и должен конструироваться и практикой. Хочу Это противоречие разрешить. Просто стараюсь добросовестно учиться только и всего.
Нет такого понятия, как "глобальный объект относительно какой-нибудь функции". Есть глобальное пространство имен, и все объекты, расположенные в этом пространстве, называются глобальными. Кстати сказать, не надо путать глобальное пространство имен с неименованным пространством имен!
kravam
быдлокодер
 Аватар для kravam
1512 / 872 / 44
Регистрация: 04.06.2008
Сообщений: 5,271
13.09.2011, 18:34  [ТС]     Почему глобальный объект, объявленный до main, конструируется в ней? #16
Цитата Сообщение от grizlik78 Посмотреть сообщение
Что касается отладчика, то на мой взгляд (это лишь моё мнение, да) отладчик останавливается до вызова конструктора не по ошибке, а как раз чтобы была возможность отследить, какие объекты инициализируются до начала программы. Но я не знаю этого наверняка.
Отладчик не обязательно отражает истинное положение вещей. В ассемблерный код посмотреть надёжнее всего. Пожалуй, пойду посмотрю.
Отладчик останавливается на точке входа и на бряках. Кто не верит- пожалуйста, hiew к вашим услугам. НАйдите её вручную и сравните с тем, на чём стоит OllyDbg. И в отладчике да, именно ассемблерный код.

Добавлено через 1 минуту
Цитата Сообщение от Сыроежка Посмотреть сообщение
Нет такого понятия, как "глобальный объект относительно какой-нибудь функции". Есть глобальное пространство имен, и все объекты, расположенные в этом пространстве, называются глобальными. Кстати сказать, не надо путать глобальное пространство имен с неименованным пространством имен!
хорошо, хорошо, я понял. Ну так делать-то мне что? По разным исполняемым кодам функции разнести или что?
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16830 / 5251 / 322
Регистрация: 30.03.2009
Сообщений: 14,144
Записей в блоге: 26
13.09.2011, 18:38     Почему глобальный объект, объявленный до main, конструируется в ней? #17
Цитата Сообщение от Сыроежка Посмотреть сообщение
Нет, это будет неправильно, так как это не соответсвует букве стандарта
Насколько я знаю, стандарт не учит разработчиков, как писать компиляторы. С точки зрения пользователя, как уже писалось, нет разницы. Ну и до кучи если есть возможность, приведи выдержку из стандарта.

Цитата Сообщение от Сыроежка Посмотреть сообщение
Не только по-моему, но и в соответствии с языками С и С++ точкой входа функции является адрес этой функции, который устанавливается при редактировании связей и формировании загрузочного модуля
Я спрашивал о "точке входа", а не о "точке входа в функцию", а потому и спросил, что он имеет в виду. "Точкой входа" обычно называют точку запуска приложения (функцию _start или как-то по -другому оно моджет называться в разных системах)

Цитата Сообщение от Сыроежка Посмотреть сообщение
Точка входа у модуля одна
Что такое "точка входа модуля"?

Цитата Сообщение от kravam Посмотреть сообщение
Я нашёл противоречие между теорией, которая гласит, что если объект глобальный относительно какой-нибудь функции, то вне её он и должен конструироваться и практикой. Хочу Это противоречие разрешить. Просто стараюсь добросовестно учиться только и всего.
Ятебе уже говорил, что вставать надо не на начале функции main, а на первом операторе. Или, скомпилив код сотладочной информацией, это за тебя сделает отладчик: т.е. ты его попросишь остановться в main'е, но он поставить брекпоинт на первом операторе.

Напомню так же, что printf - это буфферизуемый вывод, а потому гарантированно ты его увидишь только по завершении исполнения программы. Если где-то в середине работы программы ты не видишь выдачи, это не значит, что printf не отработал. Честным было бы завести глобальную переменную, статически инициализировать её нулём (что будет сделано по дефолту), в конструкторе увеличить значение этой переменной, а на точке брекпоинта посмотреть значение переменной
Сыроежка
Заблокирован
13.09.2011, 18:42     Почему глобальный объект, объявленный до main, конструируется в ней? #18
Цитата Сообщение от Evg Посмотреть сообщение
Насколько я знаю, стандарт не учит разработчиков, как писать компиляторы. С точки зрения пользователя, как уже писалось, нет разницы. Ну и до кучи если есть возможность, приведи выдержку из стандарта.
Стандарт не учит писать компиляторы. Он учит тому, что можно называть языком программирования С или С++.
Что касается выдержки из стандарта, то у меня сейчас нет такой возможности ее предоставить. Я опирался на свою память.
grizlik78
Эксперт С++
 Аватар для grizlik78
1884 / 1416 / 102
Регистрация: 29.05.2011
Сообщений: 2,961
13.09.2011, 18:43     Почему глобальный объект, объявленный до main, конструируется в ней? #19
Цитата Сообщение от Evg Посмотреть сообщение
Напомню так же, что printf - это буфферизуемый вывод, а потому
О, а std::cerr, вроде, по-умолчанию без буферизации? Можно его попробовать. Хотя у kravam и компилятор-то довольно древний. Чёрт знает что там может твориться.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
13.09.2011, 18:46     Почему глобальный объект, объявленный до main, конструируется в ней?
Еще ссылки по теме:

Глобальный вектор. Почему на выходе этот массив пуст? C++
Правильно созданный глобальный объект C++
Инициализированный объект в main не виден в других функциях C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16830 / 5251 / 322
Регистрация: 30.03.2009
Сообщений: 14,144
Записей в блоге: 26
13.09.2011, 18:46     Почему глобальный объект, объявленный до main, конструируется в ней? #20
Цитата Сообщение от grizlik78 Посмотреть сообщение
О, а std::cerr, вроде, по-умолчанию без буферизации? Можно его попробовать. Хотя у kravam и компилятор-то довольно древний. Чёрт знает что там может твориться.
Да. Без буфферизации. В варианте kravam'а это будет замена "printf" на "fprintf (stderr". Хотя опять-таки чёрт его знает, что там будет с выдачей приработе из-под отладчика, терминал, как-никак, это внешнее устройство, которое работает независимо от программы. А глоабльная переменная - это часть программы
Yandex
Объявления
13.09.2011, 18:46     Почему глобальный объект, объявленный до main, конструируется в ней?
Ответ Создать тему
Опции темы

Текущее время: 21:27. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru