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

    +3

    1. 1
    2. 2
    3. 3
    4. 4
    5. 5
    6. 6
    7. 7
    while ( port->available() )
            {
                au8Buffer[ u8BufferSize ] = port->read();
                u8BufferSize ++;
    
                if (u8BufferSize >= MAX_BUFFER) bBuffOverflow = true;
            }

    Если буфер переполнился – попробуем это запомнить и... продолжим затирать память! Реальный кусок из библиотеки работы с RS485 – протоколом, применяющимся в промышленных контроллерах и все такое.

    Запостил: smart, 08 Января 2020

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

    • тип у u8BufferSize какой? если unsigned, то буфер кольцевой, но без указателя в нем смысл нет
      Ответить
      • u8 судя по всему.
        Ответить
      • Задеанонил код: https://github.com/pkourany/ModBus_RS485_Slave/blob/master/firmware/ModbusRtu.cpp#L594.
        MAX_BUFFER = 64, поэтому даже для u8 это какое-то говно.
        Ответить
        • А вдруг bBuffOverflow - это замапанный в память бит перезагрузки?
          Ответить
          • Крутая идея, но нет )
            Ответить
          • Перевёл на «WinAPI», проверь.
            #include <iostream>
            #include <cstdint>
            #include <windows.h>
            
            struct Port {
                uint8_t read()
                {
                    return 42;
                }
            
                bool available() const
                {
                    return isAvailable;
                }
            
                bool isAvailable = true;
            };
            
            Port portVal;
            Port *port = &portVal;
            constexpr size_t MAX_BUFFER = 64;
            uint8_t au8Buffer[MAX_BUFFER] = {};
            uint8_t u8BufferSize = 0;
            LPVOID flagAddr = nullptr;
            
            LONG handler(PEXCEPTION_POINTERS)
            {
                port->isAvailable = false;
                return EXCEPTION_CONTINUE_EXECUTION;
            }
            
            int main()
            {
                flagAddr = VirtualAlloc(nullptr, sizeof(bool), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE | PAGE_GUARD);
                if (!flagAddr) {
                    std::cerr << "Couldn't allocate memory: error " << GetLastError() << std::endl;
                    return EXIT_FAILURE;
                }
            
                bool & bBuffOverflow = *reinterpret_cast<bool *>(flagAddr);
                PVOID handlerAddr = AddVectoredExceptionHandler(1, &handler);
            
                while ( port->available() )
                    {
                        au8Buffer[ u8BufferSize ] = port->read();
                        u8BufferSize ++;
            
                        if (u8BufferSize >= MAX_BUFFER) bBuffOverflow = true;
                    }
            
                std::cout << "Read " << static_cast<size_t>(u8BufferSize) << " bytes." << std::endl;
                // Read 64 bytes.
            
                RemoveVectoredExceptionHandler(handlerAddr);
                VirtualFree(flagAddr, 0, MEM_RELEASE);
            
                return EXIT_SUCCESS;
            }

            https://rextester.com/ODJIH52274
            Ответить
            • Боже, сколько напыщенного типоговна и приведений... Напоминает переливание из пустого в порожнее. В дэлфях это делается куда проще, без потери работоспособности кода.

              А если не видно разницы - зачем платить больше кодить на сях?
              Именно поэтому я за "дэлфи".
              Ответить
          • > замапанный в память
            тогда где разыменовывание? или это плюсомагия?
            Ответить
            • Это вполне может быть ссылка. Я вон выше перевёл.
              Ответить
              • > bool & bBuffOverflow = *reinterpret_cast<bool *>(flagAddr);

                я тебя понял, я просто не очень умю в кресты(((
                в сишечке так нельзя, там и ссылок-то нету


                а вообще легально так делать: взять, и костануть в ссылку? Это не будет уб нигде?
                Ответить
                • А в сишке это может быть глобалка, прибитая гвоздями к нужному адресу через линкерскрипт...
                  Ответить
                  • круто, а дай пример такого скрипта?)

                    я должен сделать сивол extern, а в линкер скрипте указать ему адрс?
                    Ответить
                    • > указать ему адрес

                      Да, там можно тупо присвоить значение символу (даже выражения всякие понимает). Либо описать новый регион памяти и хуйнуть в него секцию, в которой объявлены нужные переменные (тогда они даже не extern в общем-то, просто магически оказываются где надо).
                      Ответить
                    • Тебе реальный? Зачем тебе?
                      Ответить
                • > а вообще легально так делать: взять, и костануть в ссылку? Это не будет уб нигде?
                  Если по flagAddr находится bool — полностью легально. Я ж кастую прямо в bool, на который потом создаю ссылку. Если бы «flagAddr» был укококозателем нужного типа — можно было бы вообще без кастов написать «bool bBuffOverflow = *flagAddr».

                  > в сишечке так нельзя, там и ссылок-то нету
                  Можно прибить гвоздями, как Борманд предложил. В «msvc» это делается через «__declspec(dllimport) int hujLen;», а потом линкер смотрит во все прилинкованные .obj и ищет в них этот самый hujLen.
                  Ответить
                  • Да не надо dllimport, просто extern должно хватить.
                    Ответить
        • Моя цитата взята вот отсюда https://github.com/CONTROLLINO-PLC/CONTROLLINO_Library/blob/master/MEGA/DemoModbusRTUMaster/ModbusRtu.h – это либа, которая распространяется с типа "промышленным контроллером". Позор (

          А они сами позаимствовали этот код вот отсюда: https://github.com/smarmengol/Modbus-Master-Slave-for-Arduino

          Но видимо этот говнокусок много кто накопипастил.
          Ответить
          • Controlinho
            Ответить
          • >-for-Arduino
            О да. Там еще была реализация I2C, которая уходила в бесконечный цикл при возникновении ошибки на линии. Там еще на форуме (или стековерфлоу?) рекомендовали подтягивающие резисторы поставить, конденсаторы какие-то...
            Ответить

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