1. Си / Говнокод #17554

    +143

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    #include <stdio.h>
    
    int main(void)
    {
    	int d2[3][3][3];
    	int i,i2,i3;
    	for(i = 0; i <= 3; ++i)
    		for(i2 = 0; i2 <= 3; ++i2)
    			for(i3 = 0; i3 <= 3; ++i3)
    				d2[i][i2][i3]=5;
    	i=0,i2=0,i3=0;
    	for(i = 0; i <= 3; ++i)
    		for(i2 = 0; i2 <= 3; ++i2)
    			for(i3 = 0; i3 <= 3; ++i3)
    				printf("%d\n",d2[i][i2][i3]);
    	return 0;
    }

    играюсь я короче с массивом, этот код компилируется,все печатает но в конце Segmentation fault, почему?
    gcc -Wall -Wextra -Werror -Wpedantic -ftrapv -fwrapv -fdiagnostics-show-option -std=gnu11 -o "test" "test.c"

    Запостил: pl7ofit, 01 Февраля 2015

    Комментарии (102) RSS

    • > табы
      > отсутствие фигурных скобок
      > инициализация кучи переменных в одну строчку без пробелов
      > присвоение куче переменных в одну строчку без пробелов

      ><
      Ответить
    • А вообще какого хуя <= 3, если массив zero-based (т.е. выполнится для четвертого элемента), но в инициализации объявление на три элемента?
      Ответить
    • показать все, что скрытоАстрологи объявили начало второго семестра. Количество постов "я и моя сранная лаба" удваивается
      Ответить
    • А там разве индексы за пределы массива не выходят ?
      Ответить
    • > -Wall -Wextra
      Дай я тебя обниму! Хоть кто-то читает предупреждения.
      Ответить
      • показать все, что скрытоя думаю это был бездумный копипаст
        Ответить
        • я думаю, это от отчаяния
          "Компилятор, ну найди мой косяк, ну пожалуйста!"
          Кстати, ни splint, ни cppcheck не обнаружили выход за границы.
          Ответить
          • > не обнаружили выход за границы
            А ведь это простейший случай, когда все границы и индексы известны во время компиляции... Что уж говорить о более серьезных проблемах.
            Ответить
            • Статический анализатор clang --analyze тоже этой проблемы не выявил.
              А вот AddressSanitizer проблему в рантайме зарепортил:
              =================================================================
              ==1145==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7fff03fb80fc at pc 0x0000004b7dc6 bp 0x7fff03fb7f90 sp 0x7fff03fb7f88
              WRITE of size 4 at 0x7fff03fb80fc thread T0
                  #0 0x4b7dc5 (/tmp/test+0x4b7dc5)
                  #1 0x7f23a8725ec4 (/lib/x86_64-linux-gnu/libc.so.6+0x21ec4)
                  #2 0x4b779c (/tmp/test+0x4b779c)
              
              Address 0x7fff03fb80fc is located in stack of thread T0 at offset 156 in frame
                  #0 0x4b787f (/tmp/test+0x4b787f)
              
                This frame has 5 object(s):
                  [32, 36) ''
                  [48, 156) 'd2' <== Memory access at offset 156 overflows this variable
                  [192, 196) 'i'
                  [208, 212) 'i2'
                  [224, 228) 'i3'
              Ответить
              • к слову. оптимизацию в компилере пробовали включать?

                по крайней мере гцц выдает намного больше сообщений при компиляции с оптимизацией чем без нее.
                Ответить
            • >А ведь это простейший случай, когда все границы и индексы известны во время компиляции
              Так ладно влошенность, но он же в самом верхнем цикле выходит за границу.
              Ответить
            • Ну с точки зрения компилятора границы и индексы - несколько разные вещи...
              Ответить
      • я только так и компилирую, думаю это полезно при обучении :)
        Ответить
        • показать все, что скрытоПолезно разбираться в флагах гсс, знать тонкости и мелочи. А компилировать с одним и тем же набором флагов не полезно, а удобно
          Ответить
          • В реальной жизни флажки меняешь очень редко.
            -Werror -Wall - норма жизни, только так и компиляем.

            При приступах паранойи компиляют клангом с -Weverything -Werror.
            Ответить
            • проблема с гцц что количество ворнингов зависит от уровня оптимизации.

              компилишь - ни одного ворнингра. чекинишь. на след приходят колеги и жалуются что я там за херню вчекинил, ворнинги теперь сыпятся. разница? - компилил в дебаге, они в релизе.
              Ответить
      • А расскажи-ка, реально ли вообще избавиться от всех предупреждений в -Wall? Некоторые в шаблоны залазят, например, и предупреждают о лишних проверках. А ещё некоторые предупреждают о поломке стрикт алиасинга в аналоге optional<T>, реализованном через char[sizeof(T)] (что делает его использование невозможным).
        Ответить
        • Кинь конкретные примеры, попробуем.

          > о поломке стрикт алиасинга в аналоге optional<T>, реализованном через char[sizeof(T)]
          Алиасинг между char* и T* допустим стандартом, не пойму, чего он там ругается.
          Ответить
          • Как на стеке выделить переменную типа T, но чтобы не вызывались конструкторы и деструкторы?
            union
            		{
            			char c[sizeof(T)];
            			Align<T> a;
            		} utmp;
            		T& tmp = reinterpret_cast<T&>(utmp.c); // или просто utmp, всё равно ругается

            Как написать свой аллокатор без реинтерпрет_каста?
            Ответить
            • jni/..\..\units\/container.h:162: warning: assuming signed overflow does not occur when assuming that (X + c) >= X is always true
              jni/..\..\units\/container.h: In member function 'tblib::Format& tblib::Format::ArgDig(T, int, int, int) [with const char* pat = ((const char*)((char*)(& pat_flt))), T = float]':
              void Resize (int a_size)
              		{
                    if (a_size>this->Size())    <- тута
              			{
              ...
              		if (width<=1)
              		{
              			int s = buf.Size();
              			buf.Resize(s + MAX_NUMBER_STR); <- походу отсюда
              			char* ptr = &buf[s];
              			buf.Resize(s + sprintf(ptr, pat, digits, x)); <- или отсюда
              		} else
              		{

              П.С. приходится для спринтф хардкодом выделять буфер на 64 знака, ибо снпринтф в студии-2003 нема.
              Ответить
              • Компилер тебе просто сказал, что он в оптимизациях считает, что знакового переполнения не произойдёт. Он просто видит условие, которое всегда истинно, и сообщает тебе, что если ты там рассчитывал на возможность переполнения, то ты можешь быть удивлён, ибо весь if будет выпилен к чертям.
                Ответить
                • И чо делать с этим? Тут же люди с -Werror сидят, то есть они умеют такое исправлять как-то.
                  Ответить
                  • Эта проблема проявляется только со знаковыми целыми, переполнение которых - UB.
                    Какая у тебя версия компилятора?
                    Я бы на твоём месте включил -f-no-strict-overflow
                    http://stackoverflow.com/questions/2892477/gcc-optimization-bug-and-its-practial-implication-to-project
                    Ответить
              • > П.С. приходится для спринтф хардкодом выделять буфер на 64 знака, ибо снпринтф в студии-2003 нема.
                Там есть какая-то похожая функция. sprintf_s() вроде бы.
                Ответить
                • #ifdef __MSC_VER__ итд? Заебись, у меня уже такое говно в шаблонах есть - я не нашёл вообще ни одного варианта для кой-чего без такого жёсткого условия, что компилировался бы в обоих компиляторах.
                  Ответить
                  • Запили себе compat.h, в котором недостающие функции запилены через мелкоблядские. Так хотя бы код не будет загажен ифдефами.

                    А вообще - зачем тебе в крестах спринтф?
                    Ответить
                    • Я пишу свою функцию форматирования строки.
                      Я покопался в поиске, и мне сказали, что единственный способ перевести число в строку, понимаемый обоими моими компиляторами, не хуячя ифдефы на каждый чих - это спринтф.
                      Ответить
                      • Стрингстрим не по пацански?
                        Ответить
                        • Во-первых, он неудобен.
                          "Ты заработал %i очков, а рекорд %i очков, кстати у тебя осталось %i хитпоинтов, и ты на %i уровне" - на стримах охуеешь.
                          Во-вторых, от лисапедирования перевода числа в строку это не освобождает.

                          Я тут СТЛ выкинул из сапёра (который под ведроид), так пакет (с 3 бинарниками!) похудел с 650 до 250 килобайт.
                          Ответить
                          • boost::format
                            Ответить
                            • я пишу
                              > похудел
                              а ты предлагаешь
                              > boost::format

                              не-не-не
                              Ответить
                              • > boost::format
                                фи, зачем, boost::spirit
                                Ответить
                                • Тарас же ебанётся компилить с ним... Или у генераторной части спирита код пошустрее компилится, чем у парсерной?
                                  Ответить
                                  • подозреваю, что в 2003 студии Тараса в принципе ждут сюрпризы со спиритом, не только с его скоростью компиляции
                                    но если что, Тарас, в спирите самый быстрый вывод чисел в строку и обратно, задумайся
                                    Ответить
                                    • > самый быстрый вывод чисел в строку и обратно
                                      Ну да, это очень актуально, ибо Тарас тысячи раз в секунду выводит строки в духе "Ты заработал %i очков, а рекорд %i очков, кстати у тебя осталось %i хитпоинтов, и ты на %i уровне"...
                                      Ответить
              • > this->Size()
                Он заинлайнил эти Size() и Resize() примерно до вот такого состояния:
                if (m_size + MAX_NUMBER_STR > m_size) // вот тут ругается
                После чего вспомнил, что знаковое переполнение это UB, и заметил, что если знакового переполнения не возникнет - условие будет всегда true (а если возникнет, то всем похуй, и пусть тоже будет true). Лечить можно, емнип, двумя способами - загнать под ковёр опцией -fno-strict-overflow, либо юзать беззнаковый размер, у которого UB'а при переполнении нет.
                Ответить
                • Беззнаковый размер я калёным железом выжигал отовсюду. Потому что нахрен он мне не сдался, заебали сплошные приведения в формулах, к тому же в нём нельзя хранить значения типа "неверный индекс".
                  Какая хуя компилятор сначала мне выдаёт предупреждение? Это его работа - инлайнить и находить то, что можно вырезать, и не надо мне про это сообщать.
                  Ответить
                  • Ну раз заебали - отключи этот конкретный ворнинг. Один хуй у тебя памяти не хватит на переполнение.
                    Ответить
                    • Что значит "отключи"? Это не по-пацански.
                      Я тут ещё ассерт перед ресайзом вхерачил, что типа вот точно будет новый размер больше старого, не, предупреждение никуда не делось.
                      Ответить
                      • Дык компилятор и так прекрасно видит, что новый размер больше старого, и что условие всегда истинно. Если бы не потенциальный уб при переполнении инта - он бы молча выкинул все проверки нахуй. А тут его сомнения гложут.
                        Ответить
                        • Дык я ассерт впендюрил, а он всё равно беспокоится о чём-то.
                          Ну пиздец, что это за проверки, которые не обойти ваще никак?
                          Ответить
                    • >> Один хуй у тебя памяти не хватит на переполнение.

                      У меня всего хватит.
                      Ответить
            • Пятиминутный корявый драфт, ни одного ворнинга на -Wall -Werror -Wextra в gcc 4.9:
              #include <iostream>
              
              template <class T>
              class Optional {
              public:
                  Optional() : initialized_(false) {}
              
                  Optional(const T &init) : initialized_(true) {
                      new (raw_.bytes) T(init);
                  }
              
                  template <class V>
                  Optional(const V &init) : initialized_(true) {
                      new (raw_.bytes) T(init);
                  }
              
                  Optional(const Optional &o) : initialized_(o.initialized_) {
                      if (initialized_) {
                          new (raw_.bytes) T(o.raw_.bytes);
                      }
                  }
              
                  const T & get() const {
                      return *reinterpret_cast<const T*>(raw_.bytes);
                  }
              
                  operator bool() const {
                      return initialized_;
                  }
              
              private:
                  union {
                      char bytes[sizeof(T)];
                      void *allignAsPointer;
                  } raw_;
                  bool initialized_;
              };
              
              template <typename T>
              std::ostream &operator<<(std::ostream &os, const Optional<T> &opt) {
                  if (opt) {
                      return os << opt.get();
                  }
                  return os << "None";
              }
              
              int main() {
                  Optional<int> i;
                  Optional<double> d(42);
                  std::cout << "i = " << i << "\n";
                  std::cout << "d = " << d << "\n";
                  return 0;
              }
              Ответить
              • jni/src\ChaosMinesweeper.cpp:757: note: initialized from here
                ..\units/fixed.h:66: warning: dereferencing pointer '<anonymous>' does break strict-aliasing rules
                ..\units/fixed.h:66: warning: dereferencing pointer '<anonymous>' does break strict-aliasing rules
                ..\units/tbarr.h:134: note: initialized from here

                reference operator [] (int index) {
                			assert (index>=0 && index<N);			
                tbarr.h:134: 		return MemBeg()[index];
                		}
                ...
                
                				tblib::CArray<Point, 4> pt;
                
                ChaosMinesweeper.cpp:757:	pt[0] = Point(fcx-ln, fcy-ln);
                Ответить
                • Причём внутри этого мембега (где и живёт злобный каст) он предупреждения не показывает.
                  Ответить
                • Сигнатуру MemBeg() в студию.
                  Ответить
                  • T* возвращает, а иначе б оно вообще не скомпилировалось
                    Ответить
                    • Ну там внутри поди тоже каст из массива в T* ?
                      Ответить
                      • внутри каст из массива, да
                        ок, попробую заменить на
                        &buf[0]
                        Ответить
                        • Хуй, не помогло!
                          Ответить
                        • Баф - массив из чаров? Попробуй тот приём с кастом в char *.
                          Ответить
                          • Ну да. И с прокси-char* тоже попробовал, хуй там!

                            jni/..\..\units\/tbdynarr.h:282: warning: dereferencing pointer '<anonymous>' does break strict-aliasing rules
                            jni/..\..\units\/tbdynarr.h:282: warning: dereferencing pointer '<anonymous>' does break strict-aliasing rules
                            jni/..\..\units\/tbdynarr.h:282: warning: dereferencing pointer '<anonymous>' does break strict-aliasing rules
                            jni/..\..\units\/tbarr.h:118: note: initialized from here
                            const T* MemBeg () const
                            {			
                            	const char* tmp = &memory[0];
                            	return reinterpret_cast<const T*> (tmp);
                            }
                            T* MemBeg () 
                            {			
                            	char* tmp = &memory[0];
                            	return reinterpret_cast<T*> (tmp); <- tbarr.h 118
                            }
                            Ответить
                            • БЛЯТЬ
                              Это неисправимо: https://bugzilla.redhat.com/show_bug.cgi?id=531483
                              Как обновить гцц? Мне нужен именно кросс-компилятор, и чтобы плагин его подхватил нормально.
                              Ответить
                              • > Как обновить гцц?
                                Кросс-гцц из винды под ARM? Он же из NDK берётся? Хуй знает тогда, я под виндой кросс-гцц никогда не собирал сам...
                                Ответить
                                • БЛЯ
                                  БЛЯ БЛЯ
                                  БЛЯ БЛЯ БЛЯ
                                  БЛЯ БЛЯ БЛЯ БЛЯ
                                  Ответить
                                  • У тебя какая версия gcc? Пишут, что 4.8 стоит в новых NDK.
                                    Ответить
                                    • 4.4.3
                                      Ответить
                                      • Щи. Это ж не просто говно мамонта, это закаменевшее говно динозавра.
                                        PS> Правда по сравнению со студией 2003 и селероном вполне новая версия.
                                        Ответить
                                        • > гцц 4.4.3
                                          > студия 2003
                                          Юзай древнее говно @ ругай кресты.
                                          Ответить
                                        • > вполне новая версия
                                          GCC 4.4.3: January 21, 2010
                                          5 лет всего, тащемта.

                                          Для сравнения с 2003 студией надо гцц 3.3.х.
                                          Ответить
                                        • Как вы его различаете?
                                          Ответить
                                      • Ну обнови NDK на последнее. Должно помочь. Насколько помню, свежие SDK и NDK нормально компилят под старые вёдра.
                                        Ответить
                                        • Я боюсь обновлять НДК. Я как-то обновил 7 на 9, пересобрал, так программа стала дико срать в лог чем-то, не помню уже чем. Я погуглил, нашёл, что это баг, и что его можно исправить. Я исправил, и программа стала виснуть.
                                          Пришлось срочно откатывать всё нахуй.
                                          Вот такое оно всё коричневое с разработкой под ведро.
                                          Ответить
              • Деструктор отклеился, что-то вроде:
                ~Optional() {
                    if (initialized_) get().~T();
                }
                Только неконстантный гет ещё нужен.
                Ответить
              • warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
                         return *reinterpret_cast<const T*>(raw_.bytes);
                Если -O2 включить. Обойти удалось так:
                const T & get() const {
                    const char *raw_bytes = raw_.bytes;
                    return *reinterpret_cast<const T*>(raw_bytes);
                }
                Интуиция подсказывает, что при прямом касте он считает, что char s[8] не экивалентен char *, а поэтому алиасинг якобы нарушен. Но я могу ошибаться.
                Ответить
                • Не понял, это обходится с помощью прокси - char*?
                  Ответить
                  • Ну. Джва указателя имеют право работать с одной областью памяти тогда и только тогда, когда один из них char* или они имеют одинаковый тип. А char[8] не char*.

                    Там еще какой-то вариант был, когда можно. Но я его не помню, поищи в стандарте.
                    Ответить
                  • Тарас, смотрю у тебя появился поклонник в виде гостя-ботовода.
                    Ответить
                    • А мог бы блять уникодных цветочков например подогнать, жлобина...
                      Ответить
    • (i = 0; i <= 3; ++i) поправить на (i = 0; i < 3; ++i)
      вот и всё, нет проблем, няяяя
      а, уже ответили, точно же
      Ответить
      • Кстати, если использовать C++, можно в коде автора исправить только один символ http://ideone.com/nQxUPR.
        Пробовал задефайнить int, чтобы было вообще ноль символов, но в этом случае либо <cstdio> ломается, либо, если <cstdio> раньше подключать, ломается "int main". Но как задефайнить main, чтобы там был обычный инт, не понял. Разве что, задевайнить уже в теле main, но это не так красиво.
        Ответить
        • показать все, что скрыто>>можно в коде автора исправить только один символ

          если подключить правильную библиотеку
          Ответить
        • Можно было бы сделать #define for(x) for(x)if(i<3&&i2<3&&i3<3), тогда без С++ (ну и понятно что медскиллс). Но не работает потому что автор переменные перед первым циклом не инициализировал.
          ---
          А хотя нет, не поэтому не работает. Так что видимо Си соснул.
          Ответить
          • Красиво.

            Кстати, в связи с этим пришло сейчас в голову:
            #define void void) {\
              <что надо сделать>;\
            }\
            int old_main(void
            Ответить
        • #define main main() { return real_main(); } \
              int real_main() { \
                  ... делаем всё что нужно ... \
              } \
              int dummy
          Вроде бы даже чужой код не порушит, в отличие от хаков void'а и int'а.
          Ответить
        • показать все, что скрытопереопределил <= как < - ход, достойный царя
          Ответить
    • показать все, что скрытоСтретор, это ты меня минусуешь? Но как? Ты же мертв!
      Ответить

    Добавить комментарий