Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 17, средняя оценка - 4.82
kravam
быдлокодер
1702 / 889 / 45
Регистрация: 04.06.2008
Сообщений: 5,498
#1

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

13.09.2011, 17:16. Просмотров 2224. Ответов 36
Метки нет (Все метки)

Всё просто, имеем код:
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++. Спасибо, кто откликнется.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
13.09.2011, 17:16
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Почему глобальный объект, объявленный до main, конструируется в ней? (C++):

Почему ругается на не объявленный идентификатор - C++
#include&lt;iostream&gt; #include&lt;time.h&gt; #include&lt;stdio.h&gt; #include&lt;conio.h&gt; using namespace std; int main() { int...

Глобальный объект - C++
Как сделать, чтобы я создал объект, и его видел весь файл? Суть в том, что в конструктор я хочу передать аргумент. Или нужно сделать...

Глобальный объект класса - C++
Добрый вечер всем!) Вообщем суть такая: пишу статическую библиотеку, которая состоит из кучи файлов. Есть класс, конструктор которого...

Динамический глобальный объект. - C++
Здравствуйте. Пишу Auto-Clicker . Текущая версия содержит заранее созданный массив объектов класса &quot;TClickBase&quot; в каждом объекте хранятся...

Глобальный объект класса - C++
Ребят, написал класс для реализации очереди на основе массива в отдельном юните, теперь мне нужно в другом получить объект класса, который...

Правильно созданный глобальный объект - C++
Необходимо создать создать несколько объектов классов глобально. Я делаю: Создаю h-файл. в нем объявляю(создаю) объекты. И в срр -...

36
Mr.X
Эксперт С++
3051 / 1696 / 265
Регистрация: 03.05.2010
Сообщений: 3,867
13.09.2011, 17:35 #2
Перед началом программы инициализируются только объекты POD-типов, а ваш класс имеет конструктор, определенный пользователем, поэтому POD-классом не является.
0
Сыроежка
Заблокирован
13.09.2011, 17:50 #3
Все переменные со статической памятью инициализируются нулем до выполнения программы. При этом глобальные объекты классов повторно инициализируются конструктором до точки входа main, то есть до того, как main получит управление. Тем не менее все функции вашей программы находятся в одном исполняемом модуле.
0
Evg
Эксперт CАвтор FAQ
18258 / 6383 / 440
Регистрация: 30.03.2009
Сообщений: 17,666
Записей в блоге: 28
13.09.2011, 17:59 #4
Цитата Сообщение от Сыроежка Посмотреть сообщение
то есть до того, как main получит управление
Более правильным было бы сказать "до того, как исполнится первый оператор main'а". Потому как некоторые компиляторы вызов глобальных конструкторов встраивают в самое начало main'а

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

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

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

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

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

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

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

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

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

Цитата Сообщение от kravam Посмотреть сообщение
Я нашёл противоречие между теорией, которая гласит, что если объект глобальный относительно какой-нибудь функции, то вне её он и должен конструироваться и практикой. Хочу Это противоречие разрешить. Просто стараюсь добросовестно учиться только и всего.
Отладчик не обязательно отражает истинное положение вещей. В ассемблерный код посмотреть надёжнее всего. Пожалуй, пойду посмотрю.
0
Сыроежка
Заблокирован
13.09.2011, 18:29 #15
Цитата Сообщение от kravam Посмотреть сообщение
Я нашёл противоречие между теорией, которая гласит, что если объект глобальный относительно какой-нибудь функции, то вне её он и должен конструироваться и практикой. Хочу Это противоречие разрешить. Просто стараюсь добросовестно учиться только и всего.
Нет такого понятия, как "глобальный объект относительно какой-нибудь функции". Есть глобальное пространство имен, и все объекты, расположенные в этом пространстве, называются глобальными. Кстати сказать, не надо путать глобальное пространство имен с неименованным пространством имен!
0
13.09.2011, 18:29
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
13.09.2011, 18:29
Привет! Вот еще темы с ответами:

Почему в одних случаях пишут void main(), а в других случаях int main() {return 1;} - C++
Препод мне доказывает, что void в main`е писать неправильно, а объяснить не может почему. Кто расскажет?)

Инициализированный объект в main не виден в других функциях - C++
void display() { clear(); rocket.draw(); //ОШИБКА glFlush(); glutSwapBuffers(); _time++; } int main()

Глобальный вектор. Почему на выходе этот массив пуст? - C++
юзаю либу вектор. почему на выходе этот массив пуст? std::vector&lt;int&gt; qw;//global int main() { int i=1; qw.push_back(i); ...

Как передавать объект класса в методе main, чтобы конструктор не вызывался 2 раза? - C++
Проблемы заключаются в следующем: есть класс для создания записи и класс для хранения массива этих записей. Так вот, как передавать объект...


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

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru