Разминка для мозгов: "Hello, World!"

Croessmah, с set_new_handler вопрос интересный. Но в штатном режиме эта штука предназначена всё-таки для попытки продолжить работу программы, т.е. при нормальном выполнении main() и всего того, что из неё вызывается. Вот atexit() — тут чётко: функция-хандлер отрабатывается после завершения main().

porshe, хоть это дикое извращение, но молодец! Для полного счастья я бы ещё запретил наследование от класса __not_used_class__, и объявил funcs как static.

и объявил funcs как static.

Что-то я не совсем понимаю, зачем это нужно?

Надо знать адрес (точнее говоря, символическое имя этого адреса) стека функций завершения. Маловероятно, что для этих целей используется системный стек...

Тут вы неправы. Если я правильно вас понял, то вы утверждаете, что в С\С++ существует отдельный стек для адресов возврата из функций. Но для адресов возврата в С\С++ используется обычный программый стек.

Как доказательство:

.data

hello_str_z:
    .asciz "Hello, world!\n"


.text

.globl main

main:

    pushl $hello_str_z
    call printf
    addl $4, %esp

    pushl $0
    call exit

Выполнение программы:

Hello, world!

Тестил в xubuntu 14.04 LTS, компилятор — gcc 4.8.2.

Этот код использует функции glibc (printf и exit), и при этом, для адресов возврата в этом ассемблере используется обычный стек (расположенный в сегменте стека). Так как программа работает, значит соглашение о вызовах функций у С\С++ и gas (конечно, никакого соглашения о вызовах функций у gas нет, но будем считать применяемый здесь способ стандартным) одинаковы, а значит, адреса возврата из функций в С\С++ хранятся в обычном программном стеке.

Вроде всё :)

Но для адресов возврата в С\С++ используется обычный программый стек.

Это на усмотрение компилятора. Тот же GCC имеет расширения StackGuard и Stack-Smashing Protector.

Тут вы неправы. Если я правильно вас понял, то вы утверждаете, что в С\С++ существует отдельный стек для адресов возврата из функций.

porshe, ты меня понял неправильно. Обычно (см. замечание Croessmah) в си-шных программах используется системный стек. Но, судя по описанию atexit(), ещё организуется стек на 32 значения для адресов (точек входа) дополнительных функций завершения. По сути то же самое, что ты реализовал через вектор в свой имплементации этой функции.

porshe, ты меня понял неправильно

Я не вам отвечал, а Фтьiкаю. Он, как я понял, утверждает, что для адресов возврата из функций используется отдельный стек.
А на счёт std::atexit, конечно, там используется отдельный стек или его иммитация (об этом я тоже писал).

. Тот же GCC имеет расширения StackGuard и Stack-Smashing Protector.

Ну, это уже расширения...

Чёрт. Прочитал внимательно несколько раз и понял, что ошибся я.
Извините :\

porshe,
Вырезки из книги Александреску:
Вызов стандартной функции atexit позволяет автоматически вызывать зарегистрированные ею функции при выходе из программы в порядке LIFO.
Как работает функция atexit? При каждом вызове этой функции её параметр заталкивается в закрытый стек, предусмотренный библиотекой поддержки выполнения программ на языке C (C runtime library). При выходе из приложения система поддержки выполнения программ вызывает функции, зарегестрированные функцией atexit.

Ну и на основе этой функции Александреску приводит реализацию системы контроля для удаления Singleton'ов в правильном порядке. Почитайте, будет интересно :-)

Я не вам отвечал, а Фтьiкаю.

Ну да )) Я хотел написать почти то же самое, что Фтьiкай, но он меня опередил. Переглючило.

Опаньки! Стоит пару дней не почитать форум, как за меня уже впряглись ))) Хотя, в данном случае я не против )) Здесь мы с Черепом сыграли в унисон. Я имел ввиду то же самое.

porshe, оно самое. Предупреждаю сразу, книга может быть крайне сложна для понимания.

Всё же думаю, что она не сложней книги Страуструпа?

Почитайте, увидите. Помнится, когда я Страуструпа читал налегке, эту книгу не с первого раза освоил.

Zordaxo, почитай внимательно задание для этой «разминки». Потом обсуждение и предложенные варианты решения (три страницы постов). А потом, если найдёшь новый вариант решения, welcome! — обсудим.

Иван.
У меня после компиляции получена следующая информация.
Повторял урок C++2008 несколько раз.Ошибка одна и таже.
Заранее благодарен за подсказку.
Построение начато: проект: proba4, Конфигурация: Debug Win32 ———
Компиляция...
main.cpp
Компоновка...
Внедрение манифеста...
Проект : error PRJ0003 : Ошибка при создании «mt.exe».
Журнал построения был сохранен в «file://c:\Documents and Settings\Admin\Мои документы\Visual Studio 2008\Projects\proba4\proba4\Debug\BuildLog.htm»
proba4 — ошибок 1, предупреждений 0
========== Построение: успешно: 0, с ошибками: 1, без изменений: 0, пропущено: 0 ==========

Внимание! Это довольно старый топик, посты в него не попадут в новые, и их никто не увидит. Пишите пост, если хотите просто дополнить топик, а чтобы задать новый вопрос — начните новый.

Ответить

Вы можете использовать разметку markdown для оформления комментариев и постов. Используйте функцию предпросмотра для проверки корректности разметки.

Пожалуйста, оформляйте исходный код в соответствии с правилами разметки. Для того, чтобы вставить код в комментарий, скопируйте его в текстовое поле ниже, после чего выделите то, что скопировали и нажмите кнопку «код» в панели инструментов. Иначе ваш код может принять нечитаемый вид.

Либо производите оформление кода вручную, следующим образом:

``` #include <iostream> using namespace std; int main() { // ... } ```

Предпросмотр сообщения

Ваше сообщение пусто.