С Новым годом! Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.50/4: Рейтинг темы: голосов - 4, средняя оценка - 4.50
331 / 283 / 78
Регистрация: 02.08.2016
Сообщений: 1,008
1

Простая и интересная задачка по C++: объяснить почему результат работы программы именно такой, какой он есть

26.02.2017, 18:53. Показов 715. Ответов 8
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Всем привет, я сам ещё новичок в C++(< 2 лет изучаю), но уже что-то понимаю и решил сделать задачу на основы языка для совсем зелёных, для решения из C++ вам нужно будет знать функции, cout и указатели.

Итак, задача:
Дан следующий код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
 
using std::cout;
using std::cin;
using std::endl;
 
void func1()
{
    int var;
 
    cout << "secret function " <<  var << endl;
}
 
void printHelloWorld()
{
    long *ptr = (long *)&ptr + 3;
    *ptr = (long)&func1;
    *((int *)ptr - 1) = 052;
 
    cout << "Hello, World" << endl;
}
 
int main()
{
    printHelloWorld();
 
    return 0;
}
Результат его выполнения:
Hello, World
secret function 42
Вопросы:
1 Почему выводится secret function 42, если вызывается только printHelloWorld();
2 Откуда взялось число 42?

Подсказки:
1 Не потому что 42 - это ответ на «главный вопрос Жизни, Вселенной и Всего Остального»
2 На других архитектурах и компиляторах результат может быть другим, я компилил в linux gcc 5.4.0 x64

P.S. Если не верите, можете убедиться сами https://www.tutorialspoint.com... TliUXRqc1U
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
26.02.2017, 18:53
Ответы с готовыми решениями:

Объяснить результат работы программы
public class Solution { public static void main(String args) { ...

Почему такой результат работы функции?
#include &quot;pch.h&quot; #include &lt;iostream&gt; int main() { int age; double weight; std::cout &lt;&lt;...

Почему результат работы многопоточного кода такой?
class ThreadTest { static void Main() { Thread t = new Thread(Go); ...

Почему javascript такой какой он есть?
Почему конструкция такого вида приводит далеко не к тем результатам, которые ожидается получить?...

8
223 / 213 / 80
Регистрация: 26.04.2013
Сообщений: 972
26.02.2017, 19:56 2
1.
Кликните здесь для просмотра всего текста
если я правильно понял, то тут идёт работа со стеком вызовов, но могу и ошибаться. было бы интересно узнать правильный ответ (разъяснение), ибо возможности пошагово протестировать данный код сейчас нет.

2.
Кликните здесь для просмотра всего текста
42 выводится, т.к. переменной var присваивается 052, что есть 42 в восьмиричной системе счисления
0
56 / 56 / 31
Регистрация: 24.10.2016
Сообщений: 186
26.02.2017, 20:18 3
Все это зависит от платформы и компилятора и никак не описывается стандартом C++. Например в mingw32 я получил SIGSEGV. Так что вопрос абсолютно никак не касается знания C++, а скорее знаний конкретного компилятора и abi, который он применяет для данной платформы.
0
331 / 283 / 78
Регистрация: 02.08.2016
Сообщений: 1,008
26.02.2017, 20:55  [ТС] 4
Цитата Сообщение от mat_for_c Посмотреть сообщение
если я правильно понял, то тут идёт работа со стеком вызовов, но могу и ошибаться. было бы интересно узнать правильный ответ (разъяснение), ибо возможности пошагово протестировать данный код сейчас нет.
Кликните здесь для просмотра всего текста
Да, работа со стеком программы, при вызове любой функции, сначала в стек помещаются параметры(в моём случае отсутствуют), затем в стек помещается адрес возврата(8 байт при 64 битной адресации памяти), затем происходит вызов функции printHelloWorld, по сути переход по адресу этой функции, внутри которой 8 байт на стеке резервируются под хранение регистра esp(подробнее об этом можно почитать в книгах по ассемблеру) и ещё сколько-то байт, у меня 16 под локальные переменные(компилятор может добавлять свой код, в моём случае он так и сделал). С помощью
C++
1
long *ptr = (long *)&ptr
я кладу адрес локальной переменной(т.е. адрес ячейки стека) в саму эту переменную и теперь с помощью него можно гулять по стеку, куда душе угодно, поскольку стек "растёт вниз", то, чтоб получить то, что было положено раньше, нужно увеличивать значения, я прибавляю 3, поскольку тип long, прибавляется 3*8=24 байта и теперь ptr указывает на место в памяти, где находится адрес возврата, в это место я пишу адрес функции func1 и когда функция printHelloWorld завершается, программа смело переходит по этому адресу в надежде, что вернётся на одну команду после вызова.
С 42 примерно тоже, поскольку переменные на стеке не зануляются и всё выделение памяти под локальные переменные сводится к изменению вершины стека, можно вычислить, где будет находиться var из func1 после вызова и записать туда 42, если за это время никто не запишет туда ничего другого(нарпимер инициализация переменной var может всё поломать), то cout выведет 42.

Но, как написал, OlafNestandart, это больше на знание архитектуры современных ПК и в некоторых случаях компилятор может делать не так, как я написал выше, например, параметры функции могут передаваться не через стек, а через регистры(память процессора).
1
Эксперт С++
8972 / 4318 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
26.02.2017, 21:49 5
DevAlone,
Потому что говнокод и UB
2
70 / 70 / 35
Регистрация: 06.07.2016
Сообщений: 415
26.02.2017, 22:13 6
Цитата Сообщение от OlafNestandart Посмотреть сообщение
Например в mingw32 я получил SIGSEGV
И я.
Замечательные задачки.
0
331 / 283 / 78
Регистрация: 02.08.2016
Сообщений: 1,008
26.02.2017, 22:25  [ТС] 7
Цитата Сообщение от Notoriously Посмотреть сообщение
Замечательные задачки.
Я ж написал, что в других компиляторах и на других платформах результат может быть другой, и я там приложил ссылку, где работает. Так, на всякий случай: пример искусственный и писать такое в продакшн не стоит ни в коем случае.
0
15 / 15 / 8
Регистрация: 30.03.2014
Сообщений: 75
27.02.2017, 01:02 8
Цитата Сообщение от DevAlone Посмотреть сообщение
P.S. Если не верите, можете убедиться сами https://www.tutorialspoint.com... TliUXRqc1U
Bash
1
2
3
4
5
6
sh-4.2$ g++ -o main *.cpp                                                                                                                  
sh-4.2$ main                                                                                                                               
Hello, World                                                                                                                               
secret function 42                                                                                                                         
Segmentation fault (core dumped)                                                                                                          
sh-4.2$
Так ведь и по ссылке не работает
0
331 / 283 / 78
Регистрация: 02.08.2016
Сообщений: 1,008
27.02.2017, 01:49  [ТС] 9
Цитата Сообщение от intern Посмотреть сообщение
Так ведь и по ссылке не работает
Работает, Hello, World и secret function 42 пишет, а после этого сегфолт из-за того, что func1 была "вызвана" неправильно и адрес возврата неправильный, там находится что-то из стека, он пытается туда перейти, но ос не разрешает.
0
27.02.2017, 01:49
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
27.02.2017, 01:49
Помогаю со студенческими работами здесь

Какой результат работы этой программы?
int main(){ //(1) int var = 5; if(fork())wait(&amp;var); var++; printf(&quot;%d\n&quot;,var); return...

Перенаправление на другой web-server (задачка простая, но не пойму как это гуглу объяснить))
Доброго времени суток. Ткните пожалуйста либо в тему на форуме, либо в любую другую информацию,...

Как результат работы программы (например какой-нибудь текст) опубликовать на форуме
Можно ли сделать так чтобы результат работы программы (например какой не будь текст) публиковался...

Найти ошибки и исправить их, проанализировать полученные результаты и объяснить, почему они именно такие
Помогите,пожалуйста решить задачу, всей группой решить не можем) Постановка задачи Набрать...

можете объяснить все включая, то почему там такой step
Пример 5: Вывод элементов массива, состоящего из 10 элементов, с чётными и нечётными номерами. ...

Почему такой результат
int x = 90; x &amp;= 50; Console.WriteLine(x); Объясните пожалуйста почему...


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

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Новые блоги и статьи
Как проводить научные вычисления на Python
InfoMaster 15.01.2025
Python стал одним из наиболее востребованных языков программирования в области научных вычислений благодаря своей простоте, гибкости и обширной экосистеме специализированных библиотек. Научные. . .
Создание игры типа Minecraft на PyGame/Python: пошаговое руководство
InfoMaster 15.01.2025
В данном руководстве мы рассмотрим процесс создания игры в стиле Minecraft с использованием библиотеки PyGame на языке программирования Python. Этот проект идеально подходит как для начинающих. . .
Как создать свою первую игру в стиле Doom на Unreal Engine
InfoMaster 15.01.2025
Разработка шутера от первого лица в стиле классического Doom представляет собой увлекательное путешествие в мир игрового программирования, где сочетаются творческий подход и технические навыки. . . .
Параллельное программировани­е: основные технологии и принципы
InfoMaster 15.01.2025
Введение в параллельное программирование Параллельное программирование представляет собой фундаментальный подход к разработке программного обеспечения, который позволяет одновременно выполнять. . .
Как написать микросервис на C# с Kafka, MediatR, Redis и GitLab CI/CD
InfoMaster 15.01.2025
В современной разработке программного обеспечения микросервисная архитектура стала стандартом де-факто для создания масштабируемых и гибких приложений. Этот подход позволяет разделить сложную систему. . .
Что такое CQRS и как это реализовать на C# с MediatR
InfoMaster 15.01.2025
Концепция CQRS и её роль в современной разработке В современном мире разработки программного обеспечения архитектурные паттерны играют ключевую роль в создании масштабируемых и поддерживаемых. . .
Как настроить CI/CD с Azure DevOps
InfoMaster 15.01.2025
CI/ CD, или непрерывная интеграция и непрерывное развертывание, представляет собой современный подход к разработке программного обеспечения, который позволяет автоматизировать и оптимизировать процесс. . .
Как настроить CI/CD с помощью Jenkins
InfoMaster 15.01.2025
Введение в CI/ CD и Jenkins В современной разработке программного обеспечения непрерывная интеграция (CI) и непрерывная доставка (CD) стали неотъемлемыми элементами процесса создания качественных. . .
Как написать микросервис на Go/Golang с Kafka, REST и GitHub CI/CD
InfoMaster 14.01.2025
Определение микросервиса, преимущества использования Go/ Golang Микросервис – это архитектурный подход к разработке программного обеспечения, при котором приложение состоит из небольших, независимо. . .
Как написать микросервис с нуля на C# с RabbitMQ, CQRS, Swagger и CI/CD
InfoMaster 14.01.2025
В современном мире разработки программного обеспечения микросервисная архитектура стала стандартом де-факто для создания масштабируемых и гибких приложений. Этот архитектурный подход предполагает. . .
Как создать интернет-магазин на PHP и JavaScript
InfoMaster 14.01.2025
В современном мире электронная коммерция стала неотъемлемой частью бизнеса. Создание собственного интернет-магазина открывает широкие возможности для предпринимателей, позволяя достичь большей. . .
Как написать Тетрис на Ассемблере
InfoMaster 14.01.2025
Тетрис – одна из самых узнаваемых и популярных компьютерных игр, созданная в 1984 году советским программистом Алексеем Пажитновым. За прошедшие десятилетия она завоевала симпатии миллионы людей по. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru