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

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

13.09.2011, 17:16. Показов 4481. Ответов 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
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
13.09.2011, 17:16
Ответы с готовыми решениями:

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

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

Почему ругается на не объявленный идентификатор
#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...

36
Эксперт С++
 Аватар для Mr.X
3225 / 1752 / 436
Регистрация: 03.05.2010
Сообщений: 3,867
13.09.2011, 17:35
Перед началом программы инициализируются только объекты POD-типов, а ваш класс имеет конструктор, определенный пользователем, поэтому POD-классом не является.
0
Заблокирован
13.09.2011, 17:50
Все переменные со статической памятью инициализируются нулем до выполнения программы. При этом глобальные объекты классов повторно инициализируются конструктором до точки входа main, то есть до того, как main получит управление. Тем не менее все функции вашей программы находятся в одном исполняемом модуле.
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
13.09.2011, 17:59
Цитата Сообщение от Сыроежка Посмотреть сообщение
то есть до того, как main получит управление
Более правильным было бы сказать "до того, как исполнится первый оператор main'а". Потому как некоторые компиляторы вызов глобальных конструкторов встраивают в самое начало main'а

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

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

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

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

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

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

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

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

Добавлено через 1 минуту
Сыроежка, имеется ввиду не точка входа в функцию, какую-либо, но точка входа в исполняемый файл. Немного корявое определение, но именно о нём и идёт речь.
Точка входа у модуля одна, если только конечно это не модуль, написанный на ассемблере, где можно самостоятельно устанавливать несколько точек входа. Кроме того, когда вы устанавливаете свой отладчик на точке входа main, он пропускает инициализирующий код, то есть не обязательно сам этот код, который может находиться в любом месте модуля, а его вызов. То есть его вызов происходит до точки входа в main, ко крайней мере должно быть так.
0
Эксперт С++
 Аватар для grizlik78
2382 / 1666 / 279
Регистрация: 29.05.2011
Сообщений: 3,402
13.09.2011, 18:19
Цитата Сообщение от kravam Посмотреть сообщение
Сыроежка, я не понял, у меня шанс есть какой-нибудь?
А можешь сказать зачем тебе это? Мне просто интересно, какая разница, в каком месте вызывается конструктор.
0
Заблокирован
13.09.2011, 18:19
Цитата Сообщение от grizlik78 Посмотреть сообщение
А какая, по большому счёту разница, если стандарт С++ не разрешает получение адреса функции main()? Правда как-раз именно GCC это ограничение не выполняет и разрешает рекурсивный вызов функции main() в C++.
Вы путаете получение этого адреса внутри кода main, и тем, что отладчик знает этот адрес, так как он владеет всем модулем, а не только начиная с main, как это имеет место в отношении пользовательского кода.
0
Эксперт С++
 Аватар для grizlik78
2382 / 1666 / 279
Регистрация: 29.05.2011
Сообщений: 3,402
13.09.2011, 18:22
Цитата Сообщение от Сыроежка Посмотреть сообщение
Вы рутаете получение этого адреса внутри кода main, и тем, что отладчик знает этот адрес, так как он владеет всем модулем, а не только начиная с main, как это имеет место в отношении пользовательского кода.
Я не путаю. Отладчик меня вообще не интересует. Я спрашиваю с точки зрения разработчика программы, а не с точки зрения разработчика компилятора или отладчика. Так какая разница, в каком месте вызывается конструктор, если он в любом случае вызывается до пользовательского кода из main()?
0
быдлокодер
 Аватар для kravam
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,705
13.09.2011, 18:27  [ТС]
Я нашёл противоречие между теорией, которая гласит, что если объект глобальный относительно какой-нибудь функции, то вне её он и должен конструироваться и практикой. Хочу Это противоречие разрешить. Просто стараюсь добросовестно учиться только и всего.
0
Заблокирован
13.09.2011, 18:28
Цитата Сообщение от grizlik78 Посмотреть сообщение
Я не путаю. Отладчик меня вообще не интересует. Я спрашиваю с точки зрения разработчика программы, а не с точки зрения разработчика компилятора или отладчика. Так какая разница, в каком месте вызывается конструктор, если он в любом случае вызывается до пользовательского кода из main()?
Возможно, с практической точки зрения никакой, но тем не менее стандарт говорит по этому поводу вполне определенно. Поэтому я и написал, что разработчики компиляторов делают это на свой страх и риск.
0
Эксперт С++
 Аватар для grizlik78
2382 / 1666 / 279
Регистрация: 29.05.2011
Сообщений: 3,402
13.09.2011, 18:29
Что касается отладчика, то на мой взгляд (это лишь моё мнение, да) отладчик останавливается до вызова конструктора не по ошибке, а как раз чтобы была возможность отследить, какие объекты инициализируются до начала программы. Но я не знаю этого наверняка.

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

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

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

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

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

Напомню так же, что printf - это буфферизуемый вывод, а потому гарантированно ты его увидишь только по завершении исполнения программы. Если где-то в середине работы программы ты не видишь выдачи, это не значит, что printf не отработал. Честным было бы завести глобальную переменную, статически инициализировать её нулём (что будет сделано по дефолту), в конструкторе увеличить значение этой переменной, а на точке брекпоинта посмотреть значение переменной
0
Заблокирован
13.09.2011, 18:42
Цитата Сообщение от Evg Посмотреть сообщение
Насколько я знаю, стандарт не учит разработчиков, как писать компиляторы. С точки зрения пользователя, как уже писалось, нет разницы. Ну и до кучи если есть возможность, приведи выдержку из стандарта.
Стандарт не учит писать компиляторы. Он учит тому, что можно называть языком программирования С или С++.
Что касается выдержки из стандарта, то у меня сейчас нет такой возможности ее предоставить. Я опирался на свою память.
0
Эксперт С++
 Аватар для grizlik78
2382 / 1666 / 279
Регистрация: 29.05.2011
Сообщений: 3,402
13.09.2011, 18:43
Цитата Сообщение от Evg Посмотреть сообщение
Напомню так же, что printf - это буфферизуемый вывод, а потому
О, а std::cerr, вроде, по-умолчанию без буферизации? Можно его попробовать. Хотя у kravam и компилятор-то довольно древний. Чёрт знает что там может твориться.
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
13.09.2011, 18:46
Цитата Сообщение от grizlik78 Посмотреть сообщение
О, а std::cerr, вроде, по-умолчанию без буферизации? Можно его попробовать. Хотя у kravam и компилятор-то довольно древний. Чёрт знает что там может твориться.
Да. Без буфферизации. В варианте kravam'а это будет замена "printf" на "fprintf (stderr". Хотя опять-таки чёрт его знает, что там будет с выдачей приработе из-под отладчика, терминал, как-никак, это внешнее устройство, которое работает независимо от программы. А глоабльная переменная - это часть программы
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
13.09.2011, 18:46
Помогаю со студенческими работами здесь

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

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

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

Глобальный объект
Можете объяснить такие вещи: 1)Название объекта в каждой среде разное?(то есть в ecmascript-object,в браузере-window) 2)Доступ к этим...

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


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Уведомление о неверно выбранном значении справочника
Maks 06.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "НарядПутевка", разработанного в конфигурации КА2. Задача: уведомлять пользователя, если в документе выбран неверный склад. . .
Установка Qt Creator для C и C++: ставим среду, CMake и MinGW без фреймворка Qt
8Observer8 05.04.2026
Среду разработки Qt Creator можно установить без фреймворка Qt. Есть отдельный репозиторий для этой среды: https:/ / github. com/ qt-creator/ qt-creator, где можно скачать установщик, на вкладке Releases:. . .
AkelPad-скрипты, структуры, и немного лирики..
testuser2 05.04.2026
Такая программа, как AkelPad существует уже давно, и также давно существуют скрипты под нее. Тем не менее, прога живет, периодически что-то не спеша дополняется, улучшается. Что меня в первую очередь. . .
Отображение реквизитов в документе по условию и контроль их заполнения
Maks 04.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "ПланированиеСпецтехники", разработанного в конфигурации КА2. Данный документ берёт данные из другого нетипового документа. . .
Фото всей Земли с борта корабля Orion миссии Artemis II
kumehtar 04.04.2026
Это первое подобное фото сделанное человеком за 50 лет. Снимок называют новым вариантом легендарной фотографии «The Blue Marble» 1972 года, сделанной с борта корабля «Аполлон-17». Новое фото. . .
Вывод диалогового окна перед закрытием, если документ не проведён
Maks 04.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: реализовать программный контроль на предмет проведения документа. . .
Программный контроль заполнения реквизитов табличной части документа
Maks 02.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: 1. Реализовать контроль заполнения реквизита. . .
wmic не является внутренней или внешней командой
Maks 02.04.2026
Решение: DISM / Online / Add-Capability / CapabilityName:WMIC~~~~ Отсюда: https:/ / winitpro. ru/ index. php/ 2025/ 02/ 14/ komanda-wmic-ne-naydena/
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru