1. C++ / Говнокод #12337

    +16

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    #include <iostream>
    using namespace std;
    
    struct T{int a;T(){cout<<"T"<<this<<endl;}~T(){cout<<"~T"<<this<<endl;}};
    struct D:public T{int b;D(){cout<<"D"<<this<<endl;}~D(){cout<<"~D"<<this<<endl;}};
    
    int main() {
       T* a = new D[2];
       cout<<"mission failure"<<endl;
       delete[] a;   
       return 0;
    }

    Писал тест специально для Тараса:
    Виртуальный деструктор в базовых классах нужен:
    *Для вызова деструкторов всех потомков. Иногда это не нужно, тк поля структуры тривиальны. Согласен с Тарасом.
    *Для правильного выбора перегруженного оператора delete. Создал одним менеджером памяти, а удалил в другой - это плохо. Но также бывает редко и только в специфичных проектах.
    Но вот то, что демонстрируется в этом примере - думаю чего-нибудь такого создатели той библиотеки, что ковырял Тарас, и опасались.
    Не просто было вызван деструктор только для предков, забыв о деструкторах потомков, но и:
    *Деструктор предков был вызван для this не по тем адресам, где расположены объекты.
    Не удивлюсь, если:
    *В некоторых кулхацкерских реализациях менеджеров памяти будет удален буфер меньшего размера и куча попортится или оставшаяся не удаленная часть массива в куче просто утекет.
    http://liveworkspace.org/code/2X3MR0$8

    Запостил: LispGovno, 22 Декабря 2012

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

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

          Сам слез с крестов 3 года назад, ни о чем не жалею.
          Ответить
          • А на что переполз-то?
            Ответить
            • показать все, что скрытоДумаю на быдлопхп или быдлосишарпик.
              Ответить
              • См. ниже.
                Быдлосишарпик - хороший язык для своих задач.
                Его создатели собрались и сказали, давайте возьмем С++ и выкинем из него все детские грабли. Пусть он будет медленным и домохозяечным, зато программисты не отобьют себе яйца с первого же шага.
                Ответить
                • Медленным, домохозечным, с непредсказуемым временем выполнения любой операции (из-за потока с ГЦ).
                  Ответить
                  • Вижу, сишрпобляди неосилили С++ и из-за батхерта всех минусуют. Зато крестобоги смотрят на них как на говно.
                    Ответить
                    • Я вижу баттхёрт уборщикоблядей. Я знаю, что уборщик может быть с гарантированной верхней границй задержки, но ведь хуй кто такими пользуется, почему - не знаю. Да и нахрен они не нужны.
                      Ответить
                      • Согласен, уборьщикаблядям даже платить не нужно. Пусть убирают за еду.
                        Ответить
                • По воле долга (временно) перелез с жабы на плюсы, не сказать, что получаю баттхёрт или наступаю на грабли. Не знаю вот теперь, как буду возвращаться на жабу, где нет деструкторов, шаблонов и boost.
                  Ответить
                  • Ты серьёзно или зелёный цвет забыл?

                    ps: Метопрагромирванье забыл упомянуть.
                    Ответить
                    • > Метопрагромирванье забыл упомянуть
                      Я его не особо использую, ибо
                      1) я пишу код, который будут читать другие люди, скорее всего, не особо искушённые в мета-
                      2) нет пока особой потребности, а метапрограммирование ради метапрограммирования мне неинтересно
                      Ответить
                      • Как же так? Это свитая обязанность каждого крестушка нагенерировать кода через шаблоны, чтобы проект компилировался подольше, а тем временем:
                        http://xkcd.ru/i/303_v1.png
                        Ответить
                    • да ты просто бездушная скотина, если не плакал на его комменте
                      Ответить
                      • Я бы поплакал, если бы был уверен, что передо мной не толстый тролль. Сам понимаешь, подифолту все посты на говнокодсру зеленые.
                        Ответить
                        • Я абсолютно серьёзен и честен в этом вопросе. Не думал, что когда-нибудь буду отзываться о крестах хорошо, но этот день настал.
                          Ответить
                          • Не, ну по сравнению с жабой - да.
                            Ответить
                          • Ну вот теперь и у меня навернулись слёзы счастья. Плакать от счастья мужику - это нормально. Присоединяйтесь.
                            Ответить
                      • type implicit conversion operator как реально называется по стандарту С++? То есть под каким именем в стандарте упоминается?
                        Ответить
                        • Интересует общепринятое англицкое название оператора из следующего кода, которое упоминается в стандарте:
                          struct C
                          {
                            template<class T>
                            operator T(){return T();}
                          };
                          Ну или хотя бы на русском назовите.
                          Ответить
                          • 12.3.2 Conversion functions в c++ 98
                            Ответить
                            • Забавно, но если раскомментировать строку, то
                              http://liveworkspace.org/code/lGIIZ$21
                              , то не скомпилируется, хотя "лишний" конструктор от int максимально спрятан и вроде влиять не должен.
                              #include <iostream>
                              using namespace std;
                              struct D
                              {
                                 template<class T>
                                 operator T() const {return T();}
                              };
                              struct M
                              {
                                 M(){cout<<"M";}
                                 M(const M&){cout<<"koko";}
                                 //private: explicit M(int){cout<<"ops";}
                              };
                              int main() {
                                 M a((D()));
                                 cout<<"ko";
                                 return 0;
                              }
                              Ответить
                              • с++ 98, 12.3 Conversions, пункт 2:
                                User-defined conversions are applied only where they are unambiguous (10.2, 12.3.2). Conversions obey the access control rules (clause 11). Access control is applied after ambiguity resolution (3.4).
                                Ответить
                              • ну так ambiguous, что не так?
                                Ответить
                                • Да как верно подметил Борманд, хотелось бы private: explicit учитывать при разруливании амбигити
                                  Ответить
                                  • Эм, я наоборот подметил, что в стандарте написано, что сначала пытаются разрешить неоднозначности, и только если их нет - проверяется приватность.

                                    P.S. А иксплисит тут вообще не в тему, ты же явно юзаешь конструктор.
                                    int test(M m) {}
                                    int main() {
                                        M m(5); // тут explicit не мешает
                                        test(5); // а тут ругнется
                                        return 0;
                                    }
                                    Ответить
                  • > вот теперь, как буду возвращаться на жабу, где нет деструкторов, шаблонов и boost.
                    Но зачем?
                    > не сказать, что получаю баттхёрт или наступаю на грабли
                    Ну и на кой она нужна? По сути сей язык изобрели-то для тех кто обезьян, которые не осилили (и не смогут осилить) плюсы.
                    В плюсиках и перегрузка операторов, и лямбды.
                    А в жабе что? Мегабайты xmlя и паттерны?
                    Ведь удобней бриться острой бритвой, чем тупой жабой. Просто надо быть осмотрительным.
                    Ответить
                    • Может лучше что-то среднее, если жаба и кресты - это противоположности? Например шарпик. И не кресты, но и не жаба.
                      Ответить
                      • Шарпик - кресты 00-х. Туда пихают всё подряд, без меры.
                        Жаба просто не стала быдловской из-за неудобной либы и выского порога вхождения.
                        Для крестов был быдлер, для пхп денвер, для шарпа - студия.
                        Ответить
                        • Кресты появились раньше. С 00х шарпик разрастись не успел, поэтому пока ещё вменяем.
                          Ответить
            • Сначала по работе C#.
              Потом Common Lisp, Objective-C
              Сейчас вот опять приходится к С++ возращаться, точнее к особо извращенной гибродной его форме Objective-C++, потому что некоторые библиотеки чисто на С++, их надо как-то присовокуплять к остальному коду.

              Я не утвраждаю, что C++ говно, просто меня расстраивает неистовое стремление некоторых превратить его богатый набор возможностей в говенное кровавое месиво. И эта тенденция последнее время стала повальной.
              Ответить
              • > Objective-C++
                Что это?
                Ответить
                • Очевидно glue между C++ и Objective-C.
                  Ответить
                • Это когда в 1м файле два совершенно разным типов ООП, один от Obj-C, второй от C++
                  Че-нить типа
                  @implementation SomeClass
                  
                  - (void) someMethodWithParameter: (int) par
                  {
                    CppClass *ccpClass = new myNameSpace::cppClass(par);
                    cppClass->doSomeWork();
                    delete ccpClass;
                  }
                  
                  @end


                  Или:

                  void SomeCppClass::doSomeWork()
                  {
                      SomeObjClass *objClass = [[SomeObjClass alloc] initWithCppClass: this];
                      [objClass doSomeOtherWork];
                      [objClass release];
                  }


                  И прочий маразм :)
                  Ответить
                  • void SomeCppClass::doSomeWork()
                    {
                        SomeObjClass *objClass = [[SomeObjClass alloc] initWithCppClass: this];
                    Шизафрения.
                    Ответить
                    • Да, такое не встречается почти никогда. Но вы ведь любите клубничку?)
                      Ответить
    • > T* a = new D[2];
      Ага, а T и D разного размера, оно хоть иногда нормально работает, a[1] корректно определяется?
      Ответить
      • Неа, индексирование такого говна никогда не заработает.
        Ответить
      • Ну если
        http://liveworkspace.org/code/code/2X3MR0$9
        виртуальный деструктор добавить, то нормально удаляется.
        Ответить
        • Ага, нормально, только если в прошлом случае прогу не распидорашивало к хуям, из-за того что вызывался не тот деструктор, то теперь будет. (Что, впрочем, лучше, т.к. молчаливая ошибка хуже краша).
          Ответить
        • Ну и в чём смысл удаления этой херни, которую даже использовать нормально нельзя?
          Ответить
          • Она не удалится. delete[] посчитает это массивом более мелких элементов (T), и начнет вызывать у них по порядку деструкторы. На некоторых ему повезет, и там действительно окажется vtable от D, и вызовется деструктор от D, на некоторых вместо vtable будет хуита данные из середины других D. Собственно дойдя до кривого vtable delete[] попытается найти в нем виртуальный деструктор и ... кровь-кишки-распидорасило.

            P.S. Забавно, но в gcc delete[] вызывает деструкторы от конца массива к началу, видимо так цикл получается оптимальней, а в стандарте все равно написано, что вызовутся все, но порядок не указан. Из-за этой фишки на данном примере не получится увидеть "правильно" вызванный деструктор.
            Ответить
    • Говно ты написал очередное. Обманул бедный компилятор крестов. Кастовать указатель на массив в указатель на массив других классов нельзя. Ни при каких обстоятельствах. Кастовать можно только указатель на один объект в указатель на другой объект, то что компилятор позволяет сделать то что ты написал - так он просто не понимает, чего ты там в этих указателях держишь - массив или один объект.
      Ответить
      • Кстати надо посмотреть как адоязык это делает, у него массивы поумнее будут, стопудов где-то хранят размер элементы при выполнении.
        Ответить

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