быдлокодер
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,679
|
|||||||||||
1 | |||||||||||
Почему глобальный объект, объявленный до main, конструируется в ней?13.09.2011, 17:16. Показов 3598. Ответов 36
Метки нет (Все метки)
Всё просто, имеем код:
Так, открываем прогу в отладчике OllyDbg, стоим на точке входа (у всех своя, у меня) 401220, ставим бряк на 401290, на main, запускаем. Видим, что бряк сработал, но конструктор не вызвался! Чуть пониже в окне дизассембра видим вызов printf с аргументом "konstruktor", то есть объект конструируется в main. Как такое может быть? Компилятор g++. Спасибо, кто откликнется.
0
|
13.09.2011, 17:16 | |
Ответы с готовыми решениями:
36
Почему я не могу скрыть глобальный объект document? Почему в GUI нельзя использовать объект в main? Почему ругается на не объявленный идентификатор Глобальный объект |
3225 / 1752 / 436
Регистрация: 03.05.2010
Сообщений: 3,867
|
|
13.09.2011, 17:35 | 2 |
Перед началом программы инициализируются только объекты POD-типов, а ваш класс имеет конструктор, определенный пользователем, поэтому POD-классом не является.
0
|
Заблокирован
|
|
13.09.2011, 17:50 | 3 |
Все переменные со статической памятью инициализируются нулем до выполнения программы. При этом глобальные объекты классов повторно инициализируются конструктором до точки входа main, то есть до того, как main получит управление. Тем не менее все функции вашей программы находятся в одном исполняемом модуле.
0
|
13.09.2011, 17:59 | 4 |
Более правильным было бы сказать "до того, как исполнится первый оператор main'а". Потому как некоторые компиляторы вызов глобальных конструкторов встраивают в самое начало main'а
Что в твоём понятии есть "точка входа"? Могу тебе сказать, что это точно НЕ функция main. По честному брекпоинт надо ставить на первый оператор main'а
0
|
Заблокирован
|
|
13.09.2011, 18:05 | 5 |
Нет, это будет неправильно, так как это не соответсвует букве стандарта. Это разработчики компиляторов делают на свой страх и риск!
Не только по-моему, но и в соответствии с языками С и С++ точкой входа функции является адрес этой функции, который устанавливается при редактировании связей и формировании загрузочного модуля.
0
|
быдлокодер
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,679
|
|
13.09.2011, 18:15 [ТС] | 6 |
А я чё делаю?
Читаем внимательно, сперва ищем адрес 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 |
Точка входа у модуля одна, если только конечно это не модуль, написанный на ассемблере, где можно самостоятельно устанавливать несколько точек входа. Кроме того, когда вы устанавливаете свой отладчик на точке входа main, он пропускает инициализирующий код, то есть не обязательно сам этот код, который может находиться в любом месте модуля, а его вызов. То есть его вызов происходит до точки входа в main, ко крайней мере должно быть так.
0
|
2381 / 1665 / 279
Регистрация: 29.05.2011
Сообщений: 3,399
|
|
13.09.2011, 18:19 | 9 |
А можешь сказать зачем тебе это? Мне просто интересно, какая разница, в каком месте вызывается конструктор.
0
|
2381 / 1665 / 279
Регистрация: 29.05.2011
Сообщений: 3,399
|
|
13.09.2011, 18:22 | 11 |
Я не путаю. Отладчик меня вообще не интересует. Я спрашиваю с точки зрения разработчика программы, а не с точки зрения разработчика компилятора или отладчика. Так какая разница, в каком месте вызывается конструктор, если он в любом случае вызывается до пользовательского кода из main()?
0
|
быдлокодер
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,679
|
|
13.09.2011, 18:27 [ТС] | 12 |
Я нашёл противоречие между теорией, которая гласит, что если объект глобальный относительно какой-нибудь функции, то вне её он и должен конструироваться и практикой. Хочу Это противоречие разрешить. Просто стараюсь добросовестно учиться только и всего.
0
|
2381 / 1665 / 279
Регистрация: 29.05.2011
Сообщений: 3,399
|
|
13.09.2011, 18:29 | 14 |
Что касается отладчика, то на мой взгляд (это лишь моё мнение, да) отладчик останавливается до вызова конструктора не по ошибке, а как раз чтобы была возможность отследить, какие объекты инициализируются до начала программы. Но я не знаю этого наверняка.
Отладчик не обязательно отражает истинное положение вещей. В ассемблерный код посмотреть надёжнее всего. Пожалуй, пойду посмотрю.
0
|
Заблокирован
|
|
13.09.2011, 18:29 | 15 |
Нет такого понятия, как "глобальный объект относительно какой-нибудь функции". Есть глобальное пространство имен, и все объекты, расположенные в этом пространстве, называются глобальными. Кстати сказать, не надо путать глобальное пространство имен с неименованным пространством имен!
0
|
быдлокодер
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,679
|
|
13.09.2011, 18:34 [ТС] | 16 |
Отладчик останавливается на точке входа и на бряках. Кто не верит- пожалуйста, hiew к вашим услугам. НАйдите её вручную и сравните с тем, на чём стоит OllyDbg. И в отладчике да, именно ассемблерный код.
Добавлено через 1 минуту хорошо, хорошо, я понял. Ну так делать-то мне что? По разным исполняемым кодам функции разнести или что?
0
|
13.09.2011, 18:38 | 17 |
Насколько я знаю, стандарт не учит разработчиков, как писать компиляторы. С точки зрения пользователя, как уже писалось, нет разницы. Ну и до кучи если есть возможность, приведи выдержку из стандарта.
Я спрашивал о "точке входа", а не о "точке входа в функцию", а потому и спросил, что он имеет в виду. "Точкой входа" обычно называют точку запуска приложения (функцию _start или как-то по -другому оно моджет называться в разных системах) Что такое "точка входа модуля"? Ятебе уже говорил, что вставать надо не на начале функции main, а на первом операторе. Или, скомпилив код сотладочной информацией, это за тебя сделает отладчик: т.е. ты его попросишь остановться в main'е, но он поставить брекпоинт на первом операторе. Напомню так же, что printf - это буфферизуемый вывод, а потому гарантированно ты его увидишь только по завершении исполнения программы. Если где-то в середине работы программы ты не видишь выдачи, это не значит, что printf не отработал. Честным было бы завести глобальную переменную, статически инициализировать её нулём (что будет сделано по дефолту), в конструкторе увеличить значение этой переменной, а на точке брекпоинта посмотреть значение переменной
0
|
2381 / 1665 / 279
Регистрация: 29.05.2011
Сообщений: 3,399
|
|
13.09.2011, 18:43 | 19 |
О, а std::cerr, вроде, по-умолчанию без буферизации? Можно его попробовать. Хотя у kravam и компилятор-то довольно древний. Чёрт знает что там может твориться.
0
|
13.09.2011, 18:46 | 20 |
Да. Без буфферизации. В варианте kravam'а это будет замена "printf" на "fprintf (stderr". Хотя опять-таки чёрт его знает, что там будет с выдачей приработе из-под отладчика, терминал, как-никак, это внешнее устройство, которое работает независимо от программы. А глоабльная переменная - это часть программы
0
|
13.09.2011, 18:46 | |
13.09.2011, 18:46 | |
Помогаю со студенческими работами здесь
20
Глобальный объект Глобальный объект Глобальный объект Глобальный объект Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |