avva: (Default)
[personal profile] avva
Загадка: написать самую краткую программу на C, которая компилируется, запускается и падает. Под "компилируется" будем для ясности понимать, что "gcc -o example example.c" ее компилирует без ошибок и предупреждений, и создает исполняемый файл example, который при исполнении падает.

Вариант: то же самое, но разрешаются предупреждения при компиляции.

Теперь ответы - это не я придумал, а рассказал Даг Ландауэр (Doug Landauer) во внутренней рассылке, копирую сюда с его разрешения. Поэтому если хотите свой вариант придумать, не заглядывайте под кат:



Вариант без предупреждений: "int main;"

Вариант с предупреждениями: "main;"

Date: 2008-03-03 09:44 pm (UTC)
From: [identity profile] ohtori.livejournal.com
Сначала не заметил условие "самую краткую" и долго тормозил: в чём же сложность задачи?

Date: 2008-03-03 09:52 pm (UTC)
From: [identity profile] avva.livejournal.com
Сейчас подчеркну специально.
From: [identity profile] motto.livejournal.com
gcc -Wall test2.c
test2.c:1: warning: ‘main’ is usually a function
(это для первого варианта)
From: [identity profile] avva.livejournal.com
Я и договорился: специально написал, как именно вызывать gcc :)

Date: 2008-03-03 09:51 pm (UTC)
From: [identity profile] tsv.livejournal.com
бурные, продолжительные, переходящие в овацию
yes!

красиво.

Date: 2008-03-03 09:51 pm (UTC)
From: [identity profile] avva.livejournal.com
Правда ведь? Я тоже офигел.

Date: 2008-03-03 09:53 pm (UTC)
From: [identity profile] http://users.livejournal.com/malfet_/
int main(void) { return *((int *)0)=17;}

Date: 2008-03-03 09:56 pm (UTC)
From: [identity profile] make4um.livejournal.com
альтернативный вариант: char main; ;o)))))

Date: 2008-03-03 10:05 pm (UTC)
From: [identity profile] shabunc.livejournal.com
он длиннее на целый символ )))

Date: 2008-03-03 10:06 pm (UTC)
From: [identity profile] make4um.livejournal.com
а, да :( :о)

C warningом

Date: 2008-03-03 09:58 pm (UTC)
From: [identity profile] http://users.livejournal.com/malfet_/
int (*main)(void);

Немного подумав

Date: 2008-03-03 11:09 pm (UTC)
From: [identity profile] http://users.livejournal.com/malfet_/
Вообще это решение, так же как и авторское зависит от реализации libc. Я полагаю что можно найти комбинацию из libc+архитектуры на которой подобное переопределение символа main не будет приводить к исключению..

Date: 2008-03-03 10:08 pm (UTC)
From: [identity profile] a7sharp9.livejournal.com
Ответ можно, наверное, reverse-engineer из псевдокода (вылить воду из чайника и выключить газ), если сообразить, что достаточно записать в инструкцию типа jmp идиотский адрес, и вспомнить про entry point.

Date: 2008-03-03 10:14 pm (UTC)
From: [identity profile] tsv.livejournal.com
ну да, "когда решаешь задачу всегда полезно знать ответ"
это не претензия - просто вспомнилось

Date: 2008-03-03 10:36 pm (UTC)
From: [identity profile] jsn.livejournal.com
да-да. в досовские времена на 386+ код ребута можно было вместить в четыре байта. поэтому самый короткий reboot.c, который я писал, выглядел как main = 0xнепомнючто.

Date: 2008-03-03 11:02 pm (UTC)
From: [identity profile] spamsink.livejournal.com
Да, сейчас посложнее будет. (В линуксе) нужно перед собственно системным вызовом занести в SI значение 0x28121969 (да-да, это именно то, что вы подумали), а в DI - 0xFEElDEAD.

Угу

Date: 2008-03-04 03:06 am (UTC)
From: [identity profile] pargentum.livejournal.com
И это короткий майн тянул за собой пару килобайт из ctr0.obj.

Date: 2008-03-03 10:54 pm (UTC)
From: [identity profile] itman.livejournal.com
Ха-ха, остроумно, все мы знаем, что не слинкуется, если нет символа main. Нате вам, жрите символ main :-)

Date: 2008-03-03 11:01 pm (UTC)
nine_k: A stream of colors expanding from brain (Default)
From: [personal profile] nine_k
круто 8-)

Date: 2008-03-03 11:15 pm (UTC)
From: [identity profile] zigmar.livejournal.com
Придумать вариант не удалось, так как выяснилось что Reader автоматически показывает текст по катом :)

Date: 2008-03-03 11:30 pm (UTC)
From: [identity profile] vashik.livejournal.com
main(int argc,char **argv)
{
return *argv[argc];
}


Написал, вставил, и увидел первую строчку под катом.
До второй дошел сам. Спасибо, занимательно.

Date: 2008-03-03 11:33 pm (UTC)
From: [identity profile] urbanserj.livejournal.com
браво!

сам додумался только до main(){main();}

Date: 2008-03-04 06:29 am (UTC)
From: [identity profile] getman.livejournal.com
Компайлер ждет здесь символ main'а...

Date: 2008-03-04 07:20 am (UTC)
From: [identity profile] flaass.livejournal.com
А программа, подвешивающая gcc? Или таких уже не осталось?

Date: 2008-03-04 08:36 am (UTC)
From: [identity profile] oblomov-jerusal.livejournal.com
Если на C++ c темплэйтами, то, наверно, можно вполне легальным способом сделать переполнение стэка или ввести в бесконечный цикл?

Date: 2008-03-04 03:26 pm (UTC)
From: [identity profile] flaass.livejournal.com
Тут я усомнился. Переполнение же не подвесит компилятор - он честно выйдет по ошибке при исполнении. А вот как бы устроить бесконечный цикл?

Date: 2008-03-04 04:42 pm (UTC)
From: [identity profile] oblomov-jerusal.livejournal.com
У меня не получилось - выдает ошибку когда в попытках проделать инстанциацию темплэйта возникает цикл (класс опосредованно инстанциирует сам себя с теми же параметрами) компилятор выдает ошибку.

Date: 2008-03-04 05:06 pm (UTC)
From: [identity profile] flaass.livejournal.com
В идеальном мире (в котором компилятор вычищен от всех багов) и не должно получиться никак :)
Может, как-нибудь зациклить компилятор при вычислении константы, которую он обязан вычислить сам?

Date: 2008-03-04 06:42 pm (UTC)
From: [identity profile] oblomov-jerusal.livejournal.com
Мне казалось, темплэйты эквивалентны машине Тьюринга (так ли это?) и потому должны иметь проблему останова. Может, ограничение на глубину стека их спасает.

Date: 2008-03-04 08:45 am (UTC)
From: [identity profile] oblomov-jerusal.livejournal.com
Попробовал - похоже, циклы она выясняет и стоит ограничение на глубину в 500 темплэйтов.

Большое дерево

Date: 2008-03-04 09:04 am (UTC)
From: [identity profile] oblomov-jerusal.livejournal.com
template class A1;
template class A2;
template class A : public  A1, A2 {
};
template <> class A<0>{};
template class A1: public A {
};
template class A2: public A {
};
main(int argc, char **argv)
{
        A<16> a;
}

чтоб виднее было

Date: 2008-03-04 09:25 am (UTC)
From: [identity profile] flaass.livejournal.com
template< const int N > class A1;
template< const int N > class A2;
template< const int N > class A : public A1< N-1 >, A2< N-1 > { };
template
<> class A<0>{};
template< const int N > class A1: public A< N > { };
template< const int N > class A2: public A< N > { }; main(int argc, char **argv)
{ A<16> a; }

Date: 2008-03-04 09:36 am (UTC)
From: [identity profile] b0rg.livejournal.com
следующим постом будет задание написать маленькую программу на це, которая компилицца, запускаецца и...
и работает :)

Date: 2008-03-04 10:12 am (UTC)
From: [identity profile] ahaxopet.livejournal.com
Красиво, но эта программа не обязана упасть. В переменной main может лежать любое число, в том числе и (совершенно случайно) адрес какого-нибудь куска программы. Если очень повезет, эта программа даже сделает что-нибудь осмысленное :-)

Date: 2008-03-04 10:24 am (UTC)
From: [identity profile] plakhov.livejournal.com
В переменной main может лежать любое число

Не может, глобальные переменные гарантировано инициализируются даже в С++.

Date: 2008-03-04 10:32 am (UTC)
From: [identity profile] ahaxopet.livejournal.com
Здесь вроде бы про C разговор шел. Не помню, что в стандарте на этот счет написано, но gcc точно ничего не инициализирует:

GCC has the ability to warn the user about using the value of a uninitialized variable. Such value is undefined ... (http://gcc.gnu.org/wiki/Better_Uninitialized_Warnings)

Date: 2008-03-04 11:01 am (UTC)
From: [identity profile] ahaxopet.livejournal.com
Извиняюсь, это я не разобрался. Там про локальные переменные речь идет, хотя явно нигде это не сказано. А глобальные таки инициализируются нулем, согласен.

Date: 2008-03-04 11:09 am (UTC)
From: [identity profile] plakhov.livejournal.com
Стандарт ANSI-C это гарантирует.
Я последний раз работал с gcc лет восемь назад, поэтому ручаться за него не стану, но все же отмечу, что по Вашей ссылке ничего не говорится о глобальных переменных (локальные-то и по стандарту не должны инициализироваться автоматически).

Date: 2008-03-04 07:25 pm (UTC)
From: [personal profile] laruldan
Верно. Но это неважно. Четыре нуля вполне могут быть вполне легальной инструкцией (на x86 - это addb %al,(%eax)/addb %al,(%eax) — шансы на падение велики, но не 100% ;-)), а остальное — зависит от того, что линкер/либс уложит после main. Так что, увы, но данное решение всё-таки непереносимо — может и не упасть.

Date: 2008-03-04 07:40 pm (UTC)
From: [personal profile] laruldan
ага, насчёт шансов на падение я даже просчитался — в main не упало, $eax на входе в main указывал куда-то на стек, добежало по нулям до конца странички и только там свалилось.

Date: 2008-03-04 07:44 pm (UTC)
From: [identity profile] goshen.livejournal.com

main()
{
*((int *) 0)=0;
}

gcc4 отказывается компилировать 0[0]=0

Date: 2008-03-04 07:48 pm (UTC)
From: [identity profile] goshen.livejournal.com
правильный ответ мощный

Date: 2008-03-05 03:00 pm (UTC)
From: [identity profile] http://users.livejournal.com/_winnie/
E:\asdf>dir *.cpp
 Том в устройстве E имеет метку Новый том
 Серийный номер тома: 607E-527F

 Содержимое папки E:\asdf

05.03.2008  18:02                 0 empty.cpp
               1 файлов              
               0 папок  32 510 574 592 байт свободно

E:\asdf>g++ empty.cpp -c > out.exe

E:\asdf>out.exe
Отказано в доступе.
E:\asdf>

Date: 2008-03-06 09:48 pm (UTC)
From: (Anonymous)
Можно сделать из одного символа и без предупреждений, но с очевидным читингом.
% cat > short.c
X^D
% gcc short.c -o short -DX="int main;"
%

December 2025

S M T W T F S
  123 4 56
78 9 10 11 1213
1415 1617181920
21 22 23 24 2526 27
28293031   

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Dec. 29th, 2025 05:53 am
Powered by Dreamwidth Studios