?

Log in

Хихикс - Оживший юзерпик

Aug. 30th, 2012

06:49 pm - Хихикс

Previous Entry Share Next Entry

Что напечатает эта программа? При каких условиях? Почему? :)

#include <stdio.h>

void foo( void )
{
  int a = 42;
}

int bar( void )
{
  int b;
  return b;
}

void main( void )
{
  int c;
  
  foo();
  c = bar();
  printf( "%d\n", c );
}

Current Mood: gigglygiggly

Comments:

[User Picture]
From:vitus_wagner
Date:August 30th, 2012 02:51 pm (UTC)
(Link)
Интересно, а компиляторы уже научились to optimize out такие вещи как foo()?
(Reply) (Thread)
[User Picture]
From:_slw
Date:August 30th, 2012 02:52 pm (UTC)
(Link)
да
(Reply) (Parent) (Thread)
[User Picture]
From:shaman007
Date:August 30th, 2012 03:02 pm (UTC)
(Link)
[root@localhost ~]# gcc
gcc: не заданы входные файлы
[root@localhost ~]# vi 1.c
[root@localhost ~]# gcc 1.c
1.c: In function ‘main’:
1.c:15: предупреждение: return type of ‘main’ is not ‘int’
[root@localhost ~]# ./a.out
42
[root@localhost ~]# gcc -O3 ./1.c
./1.c: In function ‘main’:
./1.c:15: предупреждение: return type of ‘main’ is not ‘int’
[root@localhost ~]# ./a.out
-1081113660
[root@localhost ~]#
(Reply) (Parent) (Thread)
[User Picture]
From:vitus_wagner
Date:August 30th, 2012 05:16 pm (UTC)
(Link)
А зачем gcc без параметров в начале? Может gcc --version имелось в виду?
(Reply) (Parent) (Thread)
[User Picture]
From:shaman007
Date:August 30th, 2012 08:28 pm (UTC)
(Link)
Это просто я хост с gcc искал. Вышел LOR.
(Reply) (Parent) (Thread)
[User Picture]
From:alexott
Date:August 30th, 2012 05:12 pm (UTC)
(Link)
я один раз чуть не сошел с ума, пытаясь понять почему у меня в test case memchr не вызывается - поскольку я ничего не делал с его результатом, то компилятор просто выкинул соответствующий вызов :-)
(Reply) (Parent) (Thread)
[User Picture]
From:_slw
Date:August 30th, 2012 02:52 pm (UTC)
(Link)
в зависимости от компилятора, ключей оптимизации и ос -- что угодно.
но может [не]повезти и напечатает 42
(Reply) (Thread)
[User Picture]
From:maksa
Date:August 30th, 2012 02:54 pm (UTC)
(Link)
Похоже, что-то сугубо практическое спрашивается. Видимо, ответ зависит от компилятора. Да?

Edited at 2012-08-30 02:55 pm (UTC)
(Reply) (Thread)
[User Picture]
From:tobotras
Date:August 31st, 2012 02:49 am (UTC)
(Link)
Сугубо :)

http://tobotras.livejournal.com/580866.html?thread=8457730#t8457730 :)
(Reply) (Parent) (Thread)
[User Picture]
From:shaman007
Date:August 30th, 2012 03:01 pm (UTC)
(Link)
Есть вероятность, что 42.

Точнее, в случае с gcc без оптимизации это будет 42, так как он выделил память ровно под 1 переменную, так как в каждый момент времени исполнения у нас есть только 1 инт, а что он каждый раз по-разному обозван, так это проблемы тех, но не инициализирует и не очищает память.

Кстати, такие уязвимости были в SSH, кажется.

Нотариально заверенный скриншот:

[root@localhost ~]# vi 1/c
[root@localhost ~]# vi 1.c
[root@localhost ~]# gcc 1.c
1.c: In function ‘main’:
1.c:15: предупреждение: return type of ‘main’ is not ‘int’
[root@localhost ~]# ./a.out
42
[root@localhost ~]# gcc -O3 ./1.c
./1.c: In function ‘main’:
./1.c:15: предупреждение: return type of ‘main’ is not ‘int’
[root@localhost ~]# ./a.out
-1081113660
[root@localhost ~]#

Edited at 2012-08-30 03:03 pm (UTC)
(Reply) (Thread)
[User Picture]
From:caml_programmer
Date:August 30th, 2012 03:05 pm (UTC)
(Link)
gcc -O0 - 42
gcc -O1 - 0
gcc -O2 - 0
(Reply) (Thread)
[User Picture]
From:norian
Date:August 30th, 2012 03:08 pm (UTC)
(Link)
а если

void foo( void )
{
int a = 42;
int b = 43;
}

?
(Reply) (Thread)
[User Picture]
From:tobotras
Date:August 31st, 2012 02:43 am (UTC)
(Link)
Думаю, будет 42. bar() же верх стек-фрейма переиспользует, что там ниже, неважно.
(Reply) (Parent) (Thread)
[User Picture]
From:k001
Date:September 4th, 2012 11:38 pm (UTC)
(Link)
Пытаюсь вспомнить, кажется, в IA64 стек растёт вверх, а не вниз. Впрочем, то же самое будет.
(Reply) (Parent) (Thread)
[User Picture]
From:tarkhil
Date:August 30th, 2012 03:13 pm (UTC)
(Link)
Как уже отметили - в зависимости от компилятора, ОС и защиты стека - все, что угодно, включая fatal exception...
(Reply) (Thread)
[User Picture]
From:bish0nen
Date:August 31st, 2012 12:33 am (UTC)
(Link)
Не зависит ни от компилятора, ни от ОС, ни от защиты стека. Зависит от оптимизатора или отсутствия оптимизационного прохода.
(Reply) (Parent) (Thread)
[User Picture]
From:dz
Date:August 31st, 2012 03:59 am (UTC)
(Link)
от компилятора, очевидно, зависит. eax обязателен для возврата значения, но вот выделять регистры под темпы можно начиная хоть с edi.
(Reply) (Parent) (Thread)
[User Picture]
From:bish0nen
Date:August 31st, 2012 05:34 am (UTC)
(Link)
Зависит, скорее, от ABI, а компилятор энфорсит какой-то определённый ABI или позволяет выбирать из нескольких. Ничто не запрещает мне вернуть значение(-я) на стеке, регистры используются только потому, что к ним быстрее доступаться.
(Reply) (Parent) (Thread)
[User Picture]
From:tarkhil
Date:August 31st, 2012 04:04 am (UTC)
(Link)
Всякие штуки с зачисткой стека по возврату из функции мне приглючились?
(Reply) (Parent) (Thread)
[User Picture]
From:bish0nen
Date:August 31st, 2012 05:39 am (UTC)
(Link)
Куда они денутся-то. Только возвращаемое значение можно и на верхушку стека положить - как ABI велит - а потом и почистить стек, включая возвращённое значение.
(Reply) (Parent) (Thread)
[User Picture]
From:tobotras
Date:August 31st, 2012 07:26 am (UTC)
(Link)
Однозначно. Это ж какой оверхед.
(Reply) (Parent) (Thread)
[User Picture]
From:dibr
Date:August 30th, 2012 03:16 pm (UTC)
(Link)
Да что угодно в принципе, вплоть до фрагмента рутового пароля к серверу пентагона (если перед этим на этом компьютере сотрудник пентагона отсылал пароль по электронной почте коллеге, а ОС или рантайм не очищают память перед запуском задачи) :-)
С максимумами распределения на "42" (автоматические переменные без явного указания не инициализируются, выделяются в одном и том же месте, например в стеке, и это "место" совпало для a и b), и нуле (если автоматические переменные по умолчанию зануляются, или a и b оказались в разных местах, при этом b попало на заранее очищенную область).
(Reply) (Thread)
[User Picture]
From:tobotras
Date:August 31st, 2012 02:48 am (UTC)
(Link)
Покажешь мне реализацию С, где автоматические переменные обнуляются? ;-)
(Reply) (Parent) (Thread)
[User Picture]
From:dz
Date:August 31st, 2012 03:58 am (UTC)
(Link)
посмотри неинтеловские calling conventions и распределения регистров - есть процессоры, в которых возврат и временные хранятся в разных регистрах. там не сработает.

только всё это - дрочилово на устаревшие технологии.
если пишешь на си - не допускай чужого бинарного кода, вообще.
(Reply) (Parent) (Thread)
[User Picture]
From:dibr
Date:August 31st, 2012 09:49 am (UTC)
(Link)
Навскидку не покажу, но думаю, такие существуют - реализаций языка Си очень много, где-то это может оказаться особенностью архитектуры, где-то - внутренними требованиями по безопасности (почему нет), где-то - предельно упрощённый компилятор, на всякий случай инициализирующий всё...
(Reply) (Parent) (Thread)
[User Picture]
From:yurvor
Date:August 30th, 2012 04:21 pm (UTC)
(Link)
И ведь 42-то тут неспроста... Ох неспроста :)
(Reply) (Thread)
[User Picture]
From:tobotras
Date:August 31st, 2012 02:48 am (UTC)
(Link)
Конечно, неспроста. Это — мой возраст! Почти :)
(Reply) (Parent) (Thread)
[User Picture]
From:anka_sergevna
Date:September 1st, 2012 07:06 pm (UTC)
(Link)
а так же ответ на все остальные вопросы )
(Reply) (Parent) (Thread)
[User Picture]
From:votez
Date:August 30th, 2012 08:14 pm (UTC)
(Link)
а должно написать "криворукий программист, учи си шарп и не претендуй!". Если не пишет - нужен патч. Во все компиляторы под все платформы.
(Reply) (Thread)
[User Picture]
From:dz
Date:August 31st, 2012 03:52 am (UTC)
(Link)
Вообще бы она должна напечатать "не занимайтесь хуйнёй и не используйте ЯП, которые культивируют занятия хуйнёй", но, к сожалению, в зависимости от процессора, оптимизации и calling convention она может напечатать много разнообразного мусора из разных регистров и мест стека.

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

И т.п.

На x86 вполне может и 42 принтануть, если компайлер выделит eax для переменной в foo.

(Reply) (Thread)
(Deleted comment)