Самая маленькая сбойная программа на C

    Шведский студент Йеспер Эквист (Jesper Öqvist) получил в универе домашнее задание: написать самую маленькую программу C, которая вылетает с ошибкой (segfault, SIGFPE). Обычно студенты в таких ситуациях используют деление на ноль.

    int main()
    {
        return 1/0;
    }

    Из этого кода ещё можно удалить пару байтов, если вместо инструкции использовать присвоение значения переменной.

    int main()
    {
        i=1/0;
    }

    В коде не указан тип данных для переменной i. Спецификации C89 предполагают, что в таком случае подразумевается целое int. В C99 и некоторых других вариантах C это была бы ошибка. Предположим, что мы пишем на C89, в этом случае мы можем даже сократить int main() до main().

    i;
    main()
    {
        i=1/0;
    }

    Осталось всего 16 знаков, если не считать избыточных пробелов, и больше оптимизировать уже некуда. Но на самом деле можно написать ещё более короткую сбойную программу. Дело в том, что в процессе компиляции программы компилятор создаёт один или больше объектных модулей с символьными ссылками на библиотеки и статические переменные и функции.

    Символьная ссылка содержит только название переменной. Впоследствии объектный модуль обрабатывается компоновщиком, который заменяет символьные ссылки на адреса, чтобы сделать готовый исполнимый модуль.

    Компилятор устанавливает точку входа — адрес в оперативной памяти, с которого начинается выполняться программа — и привязывает к нему main в одном из объектных модулей. Вызов main означает, что мы пытаемся выполнить инструкции по адресу, на который ссылается main.

    Интересно, что компоновщик не имеет понятия о типах данных разных объектов. Так что если мы заменим main на статическую переменную, то компилятор с удовольствием создаст объектный модуль, а компоновщик потом заменит символьную ссылку на адрес в памяти.

    Йеспер Эквист предлагает такую программу на C:

    int main=0;

    Такая программа вылетает с ошибкой, потому что пытается выполнить main как функцию, в то время как компилятор поместил её в неисполняемый сегмент с данными.

    Дальнейшие оптимизации очевидны. Можно использовать вышеупомянутый трюк с сокращением int.

    main=0;

    Да и вообще, статические переменные в C по умолчанию инициализируются в ноль, так что можно сделать код ещё лаконичнее.

    main;

    Вот она, самая маленькая сбойная программа на C.
    Поделиться публикацией
    Похожие публикации
    Ой, у вас баннер убежал!

    Ну. И что?
    Реклама
    Комментарии 48
      –77
      Вспомнилось:
      image
        +37
        Ну так это задание такое, между прочем, веселое.
          +6
          Просто вспомнилась безобидная картинка. Критиковать задание я не собирался.
            +109
            Вспомнился безобидный анекдот:
            На собрании колхоза идут выборы нового председателя. Народ активно обсуждает одного успешного кандидата. Вдруг, какой-то колхозник встает и говорит:
            — Мы не можем его выбрать. У него обе дочери б… ди.
            Ему говорят:
            — Но у него нет дочерей. У него только один сын.
            Колхозник отвечает:
            — Ну, мое дело сказать, а там вы сами уже решайте.
              +12
              Хороший анекдот; кстати, весьма подошел бы к топику про пропаганду.
                +8
                Если бы не ваш коммент, не прочитал бы этот топик , а он того явно стоит…
                Благодарю =)
                  +1
                  Благодаря вашему комменту я тоже прочитал этот замечательный топик. Спасибо!
                    0
                    на то и расчёт ;)
                +3
                Там в середине кандидата прокатили с выборами из-за этого, слова сказать ему не давали, только после выбьоров он сказал, что нет дочерей.
                +1
                Вас критикуют не потому что, картинка обидная, а потому что приелась. Попробуйте внести разнообразие.
                  0
                  Ну приелась картинка, ну был не прав. Но зачем сразу в карму то лезть? Просто хотел пошутить.
                    +3
                    Перед тем как лезть в карму, лезут в ваш Хабрацентр. Заходят в посты и что видят? Ничего. Потом заходят в ответы. Что видят там? Тоже ничего. Более дотошные могут почитать ваши вопросы (которых тоже нет) и комментарии. После этого идёт оценка вашего вклада в сообщество, позволяет этот вклад так ошибаться с шутками, или нет. И только уже тогда дело доходит до кармы.
              +4
              Эту картинку запостили на хабре уже 502 раза ссылка. Вы сделали 503й по абсолютному счету и первый настолько неуместный раз.
                0
                Их уже 505. Что-то мне подсказывает, что либо это число не точное, либо одно из двух.
              +12
              Вполне можно было оформить статью как перевод, зачем делать пересказ от третьего лица, при том, что написано практически то же самое.
                +67
                Это ализар, он никогда не пишет переводов. Вместо этого он делает пересказ практически того же самого от третьего лица. :)
                  +9
                  Думая над тем, какую суть несёт ваш ответ — «Это ализар, и этим всё сказано» или «Это ализар, ему можно» — пришел к выводу, что правильное всего будет «Это хабр, и этим всё сказано».
                    +14
                    Дык они же по ППА оцениваются дороже ;)
                      0
                      Ну так alizar же вроде в ППА и не участвует :-)
                        +4
                        А я думал, что alizar давно в штате Хабра :)
                          +5
                          Я предположил, что принцип оплаты там подобный — топики писать выгоднее, чем переводы. Прям Маяковкий своего времени;)
                    +6
                    Проверено, действительно не работает :)
                      0
                      Маленькая по длине исходного текста или по объему исполняемого файла?
                        +3
                        По-моему ответ очевиден.
                          0
                          Мне кажется, что постановка задачи «исходный код на С, который компилируется в самый маленький сбойный исполняемый файл» тоже может быть интересна
                            0
                            Да, может, но ответ на ваш вопрос всё же очевиден — длина конечной программы не рассматривалась в статье в принципе. Что-то мне подсказывает, что можно уложиться в ещё меньший размер, чем исходник в этой статье.
                        0
                        В Code::bloks с компилятором gcc просто main; не компилируется, а вот int main; работает так как нужно :)
                          0
                          А у меня на маке gcc съел:
                          f0b0s-osx:tmp f0b0s$ cat 1.c
                          main;
                          f0b0s-osx:tmp f0b0s$ gcc-4.7 1.c
                          1.c:1:1: warning: data definition has no type or storage class [enabled by default]
                          f0b0s-osx:tmp f0b0s$ ./a.out
                          Bus error: 10 (core dumped)
                            0
                            gcc и на Debian лишь ругается, но компилирует:
                            > gcc a.c
                            > a.c:1: warning: data definition has no type or storage class
                            > ./a.out
                            > Segmentation fault
                              0
                              Есть такое.

                              Проверил на MinGW 4.8.0 и msvc-9.0 — оба съели int main; и оба не съели main;
                                +1
                                Вру! Под MinGW 4.8.0 и msvc-9.0 программа с кодом
                                main;

                                Компилируется и успешно падает.

                                Косяк был в том, что по умолчанию компилировал как C++ код. Если компилить как чистый C (о чем, кстати, указано в статье), все ок.
                              +6
                              В оригинале ведь есть еще «Update»:
                              Hacker News user femto pointed out that it is possible to compile and link an empty file. I did not post this because gcc will refuse to compile and link the program – it requires compiling and linking separately.
                                +7
                                Уже было на Хабре и намного раньше, чем это делал шведский студент, более того — в комментариях сами хабравчане довели вариант до идеала. Искать лень, но было, годах в 2011-2012.
                                  +9
                                  Компилед спицефик, не более.
                                  Попробуйте написать сбойную программу под весь зоопарк компиляторов, и чтобы он везде работал. И добавле в буст.
                                    +5
                                    Угу, сделать boost::failure
                                    +56
                                    Как-то на stackoverflow был задан вопрос, как в минимум кода получить исключение OutOfMemoryException (.net)? Ребята старались, пытались создать бесконечную строку, но победил такой ответ:
                                    throw new OutOfMemoryException();
                                    +11
                                    Вот, например, еще более короткая программа (вообще пустой файл), которую можно собрать специальным образом (gcc):

                                    $ cat test.c
                                    $ gcc -Wl,--unresolved-symbols=ignore-all test.c
                                    $ ./a.out
                                    Segmentation fault
                                      +6
                                      Я писал такое в университете, но всё-равно мне никто не поверит.
                                        +12
                                        … которая вылетает с ошибкой (segfault). Обычно студенты в таких ситуациях используют деление на ноль.
                                        Если понимать буквально, то деление на ноль вызывает вовсе не segmentation fault, а SIGFPE.
                                        Сегфолты связаны с ошибками обращения к памяти, и main=0 — как раз такой случай.
                                          +8
                                          Джестер Огвист (Jesper Öqvist) — почему ДжесТер, почему ОГвист? Джеспер Оквист же, не?
                                          +3
                                          Jesper Öqvist — тогда уж Еспер Эквист (ударение на и)
                                            –1
                                            Интересное задание, я призадумался. Написал бы наверное
                                            int main()
                                            {
                                            unsigned long long* k = new unsigned long long[0xFFFFFFFF];
                                            delete []k;//для очистки совести
                                            return 0;
                                            }
                                            
                                            
                                            памяти нужно 2^3*(2^32-1) = 2^35 байт = 32 гб без малого при восприятии как unsigned. Иначе 0xFFFFFFFF=-1.
                                            std::bad_alloc. по-любому.
                                              0
                                              Ребят, хватит делить на ноль, еще чуть-чуть и мы узнаем как вымерли динозавры.

                                              Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                              Самое читаемое