Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 5.00/18: Рейтинг темы: голосов - 18, средняя оценка - 5.00
быдлокодер
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,679
1

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

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

Author24 — интернет-сервис помощи студентам
Всё просто, имеем код:
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
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
13.09.2011, 17:16
Ответы с готовыми решениями:

Почему я не могу скрыть глобальный объект document?
1. Благодаря чему мы можем писать document вместо window.document? 2. Почему следующий код выводит...

Почему в GUI нельзя использовать объект в main?
Делаю в конструкторе NetBeans, и проблема в том, что я не знаю, как использовать методы, ибо, ...

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

Глобальный объект
Добрый день. Подскажите, как надо объявить класс data, так, что бы потом в начале документа...

36
Эксперт С++
3224 / 1751 / 436
Регистрация: 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
21279 / 8301 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
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
быдлокодер
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,679
13.09.2011, 18:15  [ТС] 6
Цитата Сообщение от Evg Посмотреть сообщение
Что в твоём понятии есть "точка входа"? Могу тебе сказать, что это точно НЕ функция main. По честному брекпоинт надо ставить на первый оператор main'а
А я чё делаю?
Читаем внимательно, сперва ищем адрес maina, потом в отладчике стоя в точке входа, ставим бряк на первый оператор mainф, это у меня 401290

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

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

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

Добавлено через 1 минуту
Цитата Сообщение от Сыроежка Посмотреть сообщение
Тем не менее все функции вашей программы находятся в одном исполняемом модуле.
Сыроежка, я не понял, у меня шанс есть какой-нибудь? Мне надо функции по разным исполняемым модулям разнести или как?
0
Эксперт С++
2381 / 1665 / 279
Регистрация: 29.05.2011
Сообщений: 3,399
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
Эксперт С++
2381 / 1665 / 279
Регистрация: 29.05.2011
Сообщений: 3,399
13.09.2011, 18:19 9
Цитата Сообщение от kravam Посмотреть сообщение
Сыроежка, я не понял, у меня шанс есть какой-нибудь?
А можешь сказать зачем тебе это? Мне просто интересно, какая разница, в каком месте вызывается конструктор.
0
Заблокирован
13.09.2011, 18:19 10
Цитата Сообщение от grizlik78 Посмотреть сообщение
А какая, по большому счёту разница, если стандарт С++ не разрешает получение адреса функции main()? Правда как-раз именно GCC это ограничение не выполняет и разрешает рекурсивный вызов функции main() в C++.
Вы путаете получение этого адреса внутри кода main, и тем, что отладчик знает этот адрес, так как он владеет всем модулем, а не только начиная с main, как это имеет место в отношении пользовательского кода.
0
Эксперт С++
2381 / 1665 / 279
Регистрация: 29.05.2011
Сообщений: 3,399
13.09.2011, 18:22 11
Цитата Сообщение от Сыроежка Посмотреть сообщение
Вы рутаете получение этого адреса внутри кода main, и тем, что отладчик знает этот адрес, так как он владеет всем модулем, а не только начиная с main, как это имеет место в отношении пользовательского кода.
Я не путаю. Отладчик меня вообще не интересует. Я спрашиваю с точки зрения разработчика программы, а не с точки зрения разработчика компилятора или отладчика. Так какая разница, в каком месте вызывается конструктор, если он в любом случае вызывается до пользовательского кода из main()?
0
быдлокодер
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,679
13.09.2011, 18:27  [ТС] 12
Я нашёл противоречие между теорией, которая гласит, что если объект глобальный относительно какой-нибудь функции, то вне её он и должен конструироваться и практикой. Хочу Это противоречие разрешить. Просто стараюсь добросовестно учиться только и всего.
0
Заблокирован
13.09.2011, 18:28 13
Цитата Сообщение от grizlik78 Посмотреть сообщение
Я не путаю. Отладчик меня вообще не интересует. Я спрашиваю с точки зрения разработчика программы, а не с точки зрения разработчика компилятора или отладчика. Так какая разница, в каком месте вызывается конструктор, если он в любом случае вызывается до пользовательского кода из main()?
Возможно, с практической точки зрения никакой, но тем не менее стандарт говорит по этому поводу вполне определенно. Поэтому я и написал, что разработчики компиляторов делают это на свой страх и риск.
0
Эксперт С++
2381 / 1665 / 279
Регистрация: 29.05.2011
Сообщений: 3,399
13.09.2011, 18:29 14
Что касается отладчика, то на мой взгляд (это лишь моё мнение, да) отладчик останавливается до вызова конструктора не по ошибке, а как раз чтобы была возможность отследить, какие объекты инициализируются до начала программы. Но я не знаю этого наверняка.

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

Добавлено через 1 минуту
Цитата Сообщение от Сыроежка Посмотреть сообщение
Нет такого понятия, как "глобальный объект относительно какой-нибудь функции". Есть глобальное пространство имен, и все объекты, расположенные в этом пространстве, называются глобальными. Кстати сказать, не надо путать глобальное пространство имен с неименованным пространством имен!
хорошо, хорошо, я понял. Ну так делать-то мне что? По разным исполняемым кодам функции разнести или что?
0
Evg
Эксперт CАвтор FAQ
21279 / 8301 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
13.09.2011, 18:38 17
Цитата Сообщение от Сыроежка Посмотреть сообщение
Нет, это будет неправильно, так как это не соответсвует букве стандарта
Насколько я знаю, стандарт не учит разработчиков, как писать компиляторы. С точки зрения пользователя, как уже писалось, нет разницы. Ну и до кучи если есть возможность, приведи выдержку из стандарта.

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

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

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

Напомню так же, что printf - это буфферизуемый вывод, а потому гарантированно ты его увидишь только по завершении исполнения программы. Если где-то в середине работы программы ты не видишь выдачи, это не значит, что printf не отработал. Честным было бы завести глобальную переменную, статически инициализировать её нулём (что будет сделано по дефолту), в конструкторе увеличить значение этой переменной, а на точке брекпоинта посмотреть значение переменной
0
Заблокирован
13.09.2011, 18:42 18
Цитата Сообщение от Evg Посмотреть сообщение
Насколько я знаю, стандарт не учит разработчиков, как писать компиляторы. С точки зрения пользователя, как уже писалось, нет разницы. Ну и до кучи если есть возможность, приведи выдержку из стандарта.
Стандарт не учит писать компиляторы. Он учит тому, что можно называть языком программирования С или С++.
Что касается выдержки из стандарта, то у меня сейчас нет такой возможности ее предоставить. Я опирался на свою память.
0
Эксперт С++
2381 / 1665 / 279
Регистрация: 29.05.2011
Сообщений: 3,399
13.09.2011, 18:43 19
Цитата Сообщение от Evg Посмотреть сообщение
Напомню так же, что printf - это буфферизуемый вывод, а потому
О, а std::cerr, вроде, по-умолчанию без буферизации? Можно его попробовать. Хотя у kravam и компилятор-то довольно древний. Чёрт знает что там может твориться.
0
Evg
Эксперт CАвтор FAQ
21279 / 8301 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
13.09.2011, 18:46 20
Цитата Сообщение от grizlik78 Посмотреть сообщение
О, а std::cerr, вроде, по-умолчанию без буферизации? Можно его попробовать. Хотя у kravam и компилятор-то довольно древний. Чёрт знает что там может твориться.
Да. Без буфферизации. В варианте kravam'а это будет замена "printf" на "fprintf (stderr". Хотя опять-таки чёрт его знает, что там будет с выдачей приработе из-под отладчика, терминал, как-никак, это внешнее устройство, которое работает независимо от программы. А глоабльная переменная - это часть программы
0
13.09.2011, 18:46
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
13.09.2011, 18:46
Помогаю со студенческими работами здесь

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

Глобальный объект
Есть у меня приложение с формой Win Forms(CLR) Ну у меня весь код соответственно в .h файле. Как...

Глобальный объект
Можете объяснить такие вещи: 1)Название объекта в каждой среде разное?(то есть в...

Глобальный объект
Как сделать такое: при запуске программы (т.е. появление Главной формы) я создаю объект (коллекция)...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru