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

    −16

    1. 1
    2. 2
    3. 3
    4. 4
    5. 5
    6. 6
    7. 7
    /* public static */ bool
    TestFooFactory::checkItem(const Foo& item)
    {
      if (!&item)
        return false;
      return true;
    }

    null-ccылки в C++? Легко!

    Запостил: Elvenfighter, 02 Ноября 2016

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

    • ну, если какой-то чудило изхитрился передаватьв функцию, принимающую ссылку, разыменованный nullptr, то только так и воевать.
      Ответить
      • Ну в том-то и задумка. Только вот само по себе разыменование nullptr -- это UB.
        Ответить
      • Запросто. Предположим человек работает у себя в коде с указателями, есть возможность получить нулевой указатель, а его коллега написал ему фраймверк который на входе принимает ссылки, ну человек бесхитросно возьмет код коллеги на напишет SuperDuperFramework::function(*pointer) - и весь балет.
        Ответить
        • Проблема в том, что любой адекватный компилятор этот код превратит в return true. И гцц и шланг это делают.

          В итоге вся эта петушня бесполезна. Проверять угазатель на null нужно до разыменования.
          Ответить
        • я понимаю, как работает механизм "ой я тут накодил, нужен памперс"
          Ответить
      • Пример: в реальном режиме 8086 nullptr — это то место, где хранится указатель на обработчик нулевого прерывания; разыменованный nullptr — это собственно указатель на обработчик нулевого прерывания (INT 0, вызывается при попытке деления на ноль). Для того, чтобы повесить свой обработчик с возможностью возврата к оригинальному, нужно где-то сохранить адрес оригинального обработчика. Чтобы сохранить адрес оригинального обработчика, вызываемого при попытке деления на ноль, нужно... разыменовать nullptr ну или сделать memmove/memcpy, но это совсем для слабаков.
        Ответить
      • Ваще-то можно ... была у меня динамическая либа, из которой хотелось вызвать функцию, но принимала она ссылку на собственный класс внутри (чужая либа, без хидеров).
        Сделал хидер себе вроде такого
        checkItem(const Foo* item)
        Так я уже могу вызвать эту функцию из своего кода на ++.
        Оставалась проблемка создать объект Foo ... слава яйцам, конструктор Foo там тоже экспортирован был, тупо распределял на вскидку большой кусок памяти и отдавал его конструктору из либы.

        Но вопщем-то да, ссылка - это синтаксический сахар, на самом деле там указатель.
        Ответить
        • Я правильно понимаю, что в этой твоей библиотеке функция принимала ссылку, а ты не такой как все и решил сделать ей параметр указателем? Зачем? И как так получилось, что имена совпали? Они там свои функции помечали extern C?
          Ответить
    • if (!this)
          return false;
      Ответить
      • показать все, что скрытоЯ в Objc часто так пишу. Правда там не this, а self.
        Знаешь зачем?
        Ответить
        • показать все, что скрытоНе знаю, зачем ты это делаешь в обжси, а в плюсах вызывать метод с невалидным this запрещено. Хотя я раньше так писал, потому что молодой был)))
          Ответить
          • показать все, что скрытоВ ObjC создание объекта занимает 2 шага
            1) alloc (выделение памти
            2) init (конструктор, инициализация внутреннего состояния)

            В случае ошибки тебе вернут nil. Например, если не удалось сделать alloc или init.

            Так вот вызов родительского init возвращает тебе self.
            Его нужно проверить на nil, потому что если он nil то нет смысла вызывать свой конструктор: ошибка в родителе.

            Потому в Objc можно встреить такой код
            - (id)init
            {
                self = [super init];
                if (self)
                {
                    petuhField = @"kuroshka";
                }
                return self;
            }
            Ответить
            • В крестах объект создаётся тоже в два шага, но там такой хуйни нет.
              Ответить
              • показать все, что скрытоВ крестах можно хотя-бы конструктор вызвать не вызываю вручную alloc)
                Ответить
              • Да, намешали говно с мочой (аллокацию и инициализацию). А вот то, что конструктор может что-то возвращать - это заебись. В плюсах вот без исключений никак.
                Ответить
                • показать все, что скрытоНе суди строго. Это было начало 80х.
                  Зато можно аллоцировать на разных аллокаторах в независимости от конструктора) Ну точнее раньше так было.

                  Конструктор может вернуть или nil или объект.
                  Ответить
                  • > Не суди строго. Это было начало 80х.
                    Мой первый язык, не судите строго плиз.
                    Ответить
                • да ладно? new (std::nothrow) MyClass(args...); вернет 0 если не хватило памяти на выделение.
                  Ответить
        • в плюсах эта проверка не имеет смысла, а знаешь почему?
          Ответить
          • Ещё как имеет: http://govnokod.ru/13410
            Ответить
            • раньше это было UB. Сейчас по стандарту проверка this против nullptr не имеет смысла и компиляторы спокойно могут её выкидывать
              Ответить
              • То есть компиляторы предполагают, что this не может быть нулём?
                Ответить
                • теперь по стандарту - да
                  Ответить
                  • Хочешь сказать, что раньше это не было UB?
                    Ответить
                  • > раньше это было UB
                    Ты меня запутал >_< Если раньше это было уб, то проверка и тогда не имела смысла "по стандарту".
                    Ответить
                  • А жаль... иногда удобно.
                    Ответить
                    • это неправильно. Не только с точки зрения паттернов и канонов, но также с точки зрения базовой логики, "я мыслю, и значит я существую": сомневаться в собственном существовании глупо. Не удалось создать экземпляр? - ну так обработай такой сценарий по месту неудачного создания.
                      Ответить
              • Оно и раньше и сейчас UB. Просто компиляторы стали умнее.
                Ответить
                • И шо, теперь
                  delete this;
                  this = nullptr;

                  уже не катит???
                  Ответить
                  • > this = nullptr;
                    Он же const...
                    Ответить
                    • Если точнее, то this это выражение, возвращающее prvalue. В this = nullptr столько же смысла, как и в 1 = 0.
                      Ответить
                      • вроде как в какой-то ранней итерации (типа си с классами) this можно было менять. Потом это (praise the sun) убрали
                        Ответить
                        • > this можно было менять
                          Ну это же ахуенно! Можно прямо из метода переаллоцироваться и пофиксить указатель на себя в вызывающем коде.
                          Ответить
                          • Пофиксил указатель на твоём анусе, проверь.
                            Ответить
                          • я хз, менялся ли указатель в вызывающем коде (подозреваю что нет), но суть проблемы очевидна: после самостоятельного "телепорта" все указатели извне инвалидируются и потом эту нечисть не убьешь
                            Ответить
                            • Инвалидировал твой анус, проверь.
                              Ответить
    • Последние версии гцц и шланга ругаются и выпиливают проверку нахуй
      https://godbolt.org/g/9HvU1a
      Ответить
    • Острологи объявили неделю разыменования нулевых указателей.
      Ответить

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