• Вся правда о целочисленных типах в C

    Для начала несколько вопросов:

    1. Тип char по умолчанию знаковый или нет? А int?
    2. Законно ли неявное приведение (signed char *) к (char *)? А то же для int?
    3. Сколько бит в unsigned char?
    4. Какое максимальное число гарантированно можно поместить в int? А минимальное?
    5. Тип long определённо больше, чем char, не так ли?

    Разумеется, экспериментально искать ответы на эти вопросы с помощью вашего любимого компилятора в вашей любимой системе на вашем любимом компьютере1) — не лучшая идея. Мы говорим о стандарте языка (С99 и новее).

    Если вы уверенно сможете правильно ответить на эти вопросы, тогда эта статья не для вас. В противном случае десять минут, потраченные на её чтение, будут весьма полезны.

    Предположу, что вы ответили
    1. Знаковые оба.
    2. Законны оба.
    3. 8.
    4. 2147483647. -2147483648.
    5. Конечно, Кэп.


    А правильные ответы такие
    1. char — не регламентируется, int — знаковый.
    2. Для int — законно, а для char — нет.
    3. Не менее 8.
    4. 32767. -32767
    5. Вообще говоря, нет.



    Читать дальше →
  • Удаленная переустановка Linux по ssh без доступа к консоли

    Понадобилось мне переустановить сервер, который как бы хостился у знакомых знакомых. Там был сильно устаревший Debian, а, самое главное, система стояла на обычных разделах без lvm и пространство было распределено очень не оптимально. Физический доступ получить к нему было практически нереально, местного админа попросить что-то сделать было можно, но занять это могло неделю. Виртуальный KVM у сервера был, но извне на него попасть было нельзя; у как бы хостера не было лишних IP-адресов, а внутрь его сети попасть было невозможно. Надо было переустановить сервер из-под работающей системы по ssh. Ага, давайте поменяем ротор у турбины не выключая, потом её перезапустим и будет она с новым ротором работать!
    Читать дальше →
  • Излучение сотовой связи: опасно?


      Иллюстрация: Abe V. Rotor

      Каждый день наш мозг подвергается воздействию излучения от сотовых телефонов, базовых станций, роутеров, спутников, сигнализаций, датчиков движения, радио и телевидения. ЛЭП, проводка в стенах, реликтовое излучение, гранитный щебень — все это может оказывать воздействие на клетки нашего тела. Прежде чем закрываться в клетке Фарадея и шить себе костюм из фольги, давайте посмотрим, о чём говорят нам законы физики и результаты научных исследований.
      Читать дальше →
    • Тяжелое расставание с Net-Tools

      • Tutorial

      Не секрет, что Net-Tools пора на почетную отставку. Да, многим админам и мне в том числе, до условного рефлекса Павлова знакомы команды ifconfig, route, netstat. На первый взгляд нет причин что-то менять, а лучшее как всегда враг хорошего.




      Давайте узнаем почему Net-Tools уже не тот и как безболезненно с него перейти на iproute2 .

      Читать дальше →
    • Ускоряем передачу данных в localhost

      Сделано в России

      Один из самых быстрых способ межпроцессного взаимодействия реализуется при помощи разделяемой памяти (Shared Memory). Но мне казалось не логичным, что в найденных мною алгоритмах, память всё равно нужно копировать, а после перезапуска клиента (причём он допускался только один) нужно перезапускать и сервер. Взяв волю в кулак, я решил разработать полноценный клиент-сервер с использованием разделимой памяти.
      Читать дальше →
      • +21
      • 14,3k
      • 9
    • Как приручить дракона. Краткий пример на clang-c

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

        Как и следовало ожидать, почти ничего особенного не нашлось, однако одно объявление меня заинтересовало. В нём были такие строки:

        «Кого мы возьмем «не глядя» или уровень выполняемых задач:
        Вы скачали любой open source проект, собираемый при помощи gcc (объем исходного кода более 10 мегабайт) и для самого большого файла cpp смогли построить AST дерево при помощи clang с –fsyntax-only;
        Вы скачали любой open source проект, собираемый при помощи Visual C++ (объем исходного кода более 10 мегабайт) и для самого большого файла cpp смогли построить AST дерево при помощи clang с –fsyntax-only;
        Вы смогли написать утилиту, которая выделит все места деклараций и использования локальных переменных, а также все функции, не определенные в данном файле
        ».

        Ну что же, подумал я, какое-никакое, а развлечение на вечер.


        Читать дальше →
      • Уязвимость «ВКонтакте» позволяла получить прямые ссылки на приватные фотографии



        tl;dr
        Была обнаружена уязвимость в закладках ВК, которая позволяла получать прямые ссылки на приватные фотографии из личных сообщений, альбомов любого пользователя/группы. Был написан скрипт, который перебирал фотографии пользователя за определенный период и затем, через эту уязвимость получал прямые ссылки на изображения. Если коротко, то: можно было за 1 минуту получить все ваши вчерашние фотографии, за 7 минут — все фото, загруженные на прошлой неделе, за 20 минут — прошлый месяц, за 2 часа — прошлый год. Уязвимость на данный момент исправлена. Администрация ВКонтакте выплатила вознаграждение в 10к голосов.

        История началась с того, как мне в личку во «Вконтакте» кинули изображение. Обычно, если вещь важная, я её загружаю в облако, но в моём случае в этом не было необходимости, и я решил воспользоваться функцией закладок «Вконтакте».
        Читать дальше →
      • Отладка вашей ОС: урок по выделению памяти

        • Перевод

        Всё началось, как и многие другие расследования, с баг-репорта.

        Название отчёта было довольно простым: «При HTTP-подключении iter_content медленно работает с чанками большого размера». Подобное название немедленно включило у меня в голове сирену по двум причинам. Во-первых, довольно сложно определить, что здесь означает «медленно»? Насколько медленно? Насколько велик «большой размер»? Во-вторых, если бы описанное проявлялось действительно серьёзно, то мы бы об этом уже знали. Метод iter_content используется давно, и если бы он существенно притормаживал в распространённом пользовательском режиме, то мимо нас такая информация не прошла бы.
        Читать дальше →
      • Превозмогая трудности: Gravity Defied на sed

          image Итак, эта статья посвящается тем, кто любит решать нестандартные задачи на не предназначенных для этого инструментах. Здесь я опишу основные проблемы, с которыми столкнулся во время создания аналога игры Gravity defied с использованием потокового текстового редактора (sed).

          Далее предполагается, что читатель хотя бы немного знаком с синтаксисом sed'ом и и написанием скриптов под bash.
          Читать дальше →
          • +40
          • 7,9k
          • 8
        • В C++17 до сих пор нет нормальных многомерных массивов, которые были в Fortran начиная с Fortran 90

            Это статья про многомерные массивы. А ещё про ключевое слово restrict, до появления которого в C язык Fortran был быстрее C. Немного про то, зачем я это написал, см. в конце.

            Многомерные массивы. Начну с многомерных массивов. Допустим, вам нужно максимально эффективно работать с большими квадратными матрицами в C++ (скажем, умножать их друг на друга). Причём размер матриц становится известен лишь в runtime. Что делать?

            Всякие double a[n][n] и std::array<std::array<double, n>, n> не сработают, т. к. порядок матрицы (n) будет известен лишь в runtime. new double[n][n] не сработает по этой же причине (лишь первое измерение массива, создаваемого new, может быть runtime-выражением). Попробуем так:

            double **a = new double *[n]; // Массив длины n указателей на double
            for (int i = 0; i != n; ++i)
              {
                a[i] = new double[n];
              }
            
            Читать дальше →
          • Расширения языков C и C++. Часть 1

              Данная статья (и я надеюсь что серия статей) посвящена нестандартным расширениям языков C и C++, которые существуют практически в каждом компиляторе.

              Языковые расширения — это дополнительные возможности и фичи языка, не входящие в стандарт, но тем ни менее поддерживаемые компиляторами. Исследовать эти расширения очень интересно — в первую очередь потому, что они возникли не на пустом месте; каждое расширение — результат насущной необходимости, возникавшей у большого числа программистов. А мне интересно вдвойне — поскольку мне нравятся языки программирования и я разрабатываю свой, часто оказывается что многие мои идеи реализованы именно в расширениях языка. Стандарты языков C и C++ развиваются крайне медленно, и порой, читая описание расширений, так и хочется воскликнуть «ну это же очевидно! почему этого до сих пор нет в стандарте?».

              Языковые расширения — это такая «серая», теневая область, про которую обычно мало пишут и мало знают. Но именно этим она и и интересна!

              Предварительно могу сказать, что будут рассмотрены компиляторы общего назначения gcc, msvs, clang, intel, embarcadero, компиляторы для микроконтроллеров iar и keil, и по возможности многие другие компиляторы. Больше всего расширений в GCC, что не удивительно — свободная разработка способствует воплощению разных языковых фич. К тому же, информация по расширениям GCC вся собрана в одном месте, а информацию по остальным компиляторам придется собирать по крупицам. Поэтому начнем с GCC.
              Читать дальше →
            • Манифест Ричарда Столлмана: How I do my computing

              • Перевод
              image

              Я использую компьютер Thinkpad X60, в котором FSF ( Free Software Foundation) инсталлировали свободную инициализирующую программу (initialization program, libreboot) и свободную операционную систему (Trisquel GNU/Linux). Это первая компьютерная модель со свободной инициализирующей программой и свободной операционной системой, которая когда-либо поступала в продажу. Поэтому это первый компьютерный продукт, который одобрили FSF (однако не был продан Lenovo).

              До этого я несколько лет использовал Lemote Yeeloong. На тот момент это был единственный ноутбук со свободной установочной программой и свободной операционной системой, который можно было купить. Но его никогда не продавали со свободной операционной системой.

              До этого я использовал OLPC (One Laptop Per Child) несколько недель. Я перестал, потому что проект OLPC решил поддерживать Windows, а я не хотел этого. OLPC используют особую прошивку для WiFi, поэтому я не мог использовать внутреннее WiFi устройство. Не беда, я использовал внешнее.

              Результаты меня беспокоят. Я ожидал увидеть миллионы детей, использующих Windows с OLPC. Вместо этого я вижу, как миллионы детей используют Windows с Intel Classmate.

              Раннее я пользовался устройствами полностью на свободных GNU/Linux системах, но там были несвободные BIOS. На протяжении восьми лет я пытался найти способ обойти эту проблему.
              Читать дальше →
            • Самая дорогая однобайтовая ошибка

              • Перевод
              Предлагаю вашему вниманию перевод недавнего поста в электронном журнале Queue авторства Poul-Henning Kamp.

              Ошиблись ли Кен, Деннис и Брайан при выборе использовать NUL-завершенные текстовые строки?

              ИТ стимулирует и реализует современную западную экономику. Соответственно мы часто видим заголовки про ошеломляюще огромные суммы денег, связанные с ошибками в ИТ. Какое же решение, связанное с ИТ или КН [компьютерными науками], является наиболее дорогим?
              Читать дальше →
            • О фундаментальных ошибках в дизайне языков программирования

                Как-то раз мне на глаза попалась статья о том, что самой дорогой ошибкой в дизайне языков программирования было решение определять окончание строки в C по NULL-байту. Один из вариантов перевода этой статьи на Хабре (хотя я, по-моему, читал другой). Эта статья меня немного удивила. Во-первых, как будто в те времена экономии каждого бита памяти можно было шикануть и выделить ещё 2-4 байта в каждой строке на хранение её размера. Во-вторых, никаких особо катастрофических последствий это решения для программиста не несёт. Ошибок, которые можно по этому поводу совершить я могу придумать целых две: неверно выделить память для строки (забыть место под NULL) и неверно записать строку (забыть NULL). О первой ошибке уже предупреждают компиляторы, избежать второй помогает использование библиотечных функций. Всей-то беды.

                Значительно большей проблемой времён дизайна языка С (и затем С++) мне кажется другое — оператор for. При всей его кажущейся безвредности — это просто кладезь потенциальных ошибок и проблем.

                Давайте вспомним классическое его применение:

                for (int i = 0; i < vec.size(); i++)
                {...}

                Что же здесь может пойти не так?
                Читать дальше →
              • main(){printf(&unix["\021%six\012\0"], (unix)[«have»]+«fun»-0x60);}

                • Перевод

                Развлекаемся, «распутывая» код на языке Си

                Вызов: Прежде чем лезть под кат, скомпилируйте в голове заголовок статьи, что он дает на выходе?

                image

                Когда я в очередной раз просматривал книгу «Expert C programming», я вдруг наткнулся на раздел «light relief» в международном конкурсе на самый запутанный код на Си (IOCCC). Это соревнование по написанию как можно более нечитабельного кода. То, что такие конкурсы устраиваются для Си, наверное, говорит что-что об этом языке. Мне хотелось увидеть работы участников этого соревнования. Не найдя никакой информации в интернете, я решил поискать их самостоятельно.

                IOCCC был придуман Стивеном Борном, когда он решил использовать препроцессор Си и написать Unix shell как бы на языке Си, но больше похожем на язык Algol-68, с его явными окончаниями операторов, например:

                if
                  ...
                fi 

                Он добился этого, сделав:

                #define IF if(
                #define THEN ){
                #define ELSE } else {
                #define FI ;}
                

                Что позволило ему писать так:

                IF *s2++ == 0
                THEN return(0);
                FI
                

                Читать дальше →
                • +53
                • 16,6k
                • 4
              • Оптимизация кода: память

                  Большинство программистов представляют вычислительную систему как процессор, который выполняет инструкции, и память, которая хранит инструкции и данные для процессора. В этой простой модели память представляется линейным массивом байтов и процессор может обратиться к любому месту в памяти за константное время. Хотя это эффективная модель для большинства ситуаций, она не отражает того, как в действительности работают современные системы.

                  В действительности система памяти образует иерархию устройств хранения с разными ёмкостями, стоимостью и временем доступа. Регистры процессора хранят наиболее часто используемые данные. Маленькие быстрые кэш-памяти, расположенные близко к процессору, служат буферными зонами, которые хранят маленькую часть данных, расположеных в относительно медленной оперативной памяти. Оперативная память служит буфером для медленных локальных дисков. А локальные диски служат буфером для данных с удалённых машин, связанных сетью.

                  image

                  Иерархия памяти работает, потому что хорошо написанные программы имеют тенденцию обращаться к хранилищу на каком-то конкретном уровне более часто, чем к хранилищу на более низком уровне. Так что хранилище на более низком уровне может быть медленнее, больше и дешевле. В итоге мы получаем большой объём памяти, который имеет стоимость хранилища в самом низу иерархии, но доставляет данные программе со скоростью быстрого хранилища в самом верху иерархии.
                  Читать дальше →
                • Эксперименты с malloc

                    image

                    Как известно, в современных архитектурах x86(_64) и ARM виртуальная память процесса линейна и непрерывна, ибо, к счастью, прошли времена char near* и int huge*. Виртуальная память поделена на страницы, типичный размер которых 4 KiB, и по умолчанию они не отображены на физическую память (mapping), так что работать с ними не получится. Чтобы посмотреть текущие отображённые интервалы адресов у процесса, в Linux смотрим /proc/<pid>/maps, в OS X vmmap <pid>. У каждого интервала адресов есть три вида защиты: от исполнения, от записи и от чтения. Как видно, самый первый интервал, начинающийся с load address (соответствующий сегменту .text у ELF в Linux, __TEXT у Mach-O в OS X), доступен на чтение и исполнение — очень логично. Ещё можно увидеть, что стек по сути ничем не отличается от других интервалов, и можно быстро вычислить его размер, вычтя из конечного адреса начальный. Отображение страниц выполняется с помощью mmap/munmap, а защита меняется с помощью mprotect. Ещё существуют brk/sbrk, deprecated древние пережитки прошлого, которые изменяют размер одного-единственного интервала «данных» и в современных системах эмулируются mmap’ом.

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

                    • оптимально управляет уже выделенной памятью;
                    • значительно уменьшает количество обращений к ядру (ведь mmap / sbrk — это syscall);
                    • вообще абстрагирует программиста от виртуальной памяти, так что многие пользуются malloc’ом, вообще не подозревая о существовании страниц, таблиц трансляции и т. п.

                    Довольно теории! Будем щупать malloc на практике. Проведём три эксперимента. Работа будет возможна на POSIX-совместимых операционках, в частности была проверена работа на Linux и на OS X.
                    Читать дальше →
                  • Как спасти принцессу, используя 8(+45) языков программирования, в пятницу

                    • Перевод


                    У вас есть JavaScript. Вы тратите несколько часов на сбор библиотек, настройку node и постройку фреймворка для замка. К тому времени, как вы разберетесь с фреймворком, форт уже будет заброшен, а принцесса переберется в другой замок.



                    У вас есть С. У вас есть библиотека для замка и для принцессы. В атаку! Вы спасаете принцессу, ее собаку, весь ее гардероб и всё, что она когда-либо съела. Fuck, неужели я забыл null-terminator?
                    Читать дальше →
                  • Подводные камни Bash

                    • Перевод


                    В этой статье мы поговорим об ошибках, совершаемых программистами на Bash. Во всех приведённых примерах есть какие-то изъяны. Вам удастся избежать многих из нижеописанных ошибок, если вы всегда будете использовать кавычки и никогда не будете использовать разбиение на слова (wordsplitting)! Разбиение на слова — это ущербная легаси-практика, унаследованная из оболочки Bourne. Она применяется по умолчанию, если вы не заключаете подстановки (expansions) в кавычки. В общем, подавляющее большинство подводных камней так или иначе связаны с подстановкой без кавычек, что приводит к разбиению на слова и глоббингу (globbing) получившегося результата.


                    Читать дальше →
                  • Null, великий и ужасный

                      Ошибка дизайна


                      Именно так и никак иначе: null в C# — однозначно ошибочное решение, бездумно скопированное из более ранних языков.


                      1. Самое страшное: в качестве значения любого ссылочного типа может использоваться универсальный предатель — null, на которого никак не среагирует компилятор. Зато во время исполнения легко получить нож в спину — NullReferenceException. Обрабатывать это исключение бесполезно: оно означает безусловную ошибку в коде.
                      2. Перец на рану: сбой (NRE при попытке разыменования) может находится очень далеко от дефекта (использование null там, где ждут полноценный объект).
                      3. Упитанный пушной зверек: null неизлечим — никакие будущие нововведения в платформе и языке не избавят нас от прокаженного унаследованного кода, который физически невозможно перестать использовать.

                      Этот ящик Пандоры был открыт еще при создании языка ALGOL W великим Хоаром, который позднее назвал собственную идею ошибкой на миллиард долларов.

                      На самом деле все не так плохо