Проверка open-source игры Multi Theft Auto

    MTA & PVS-Studio
    Мы давно не проверяли игры с помощью PVS-Studio. Решили это исправить и выбрали проект MTA. Multi Theft Auto (MTA) является модификацией для PC версий игры Grand Theft Auto: San Andreas от Rockstar North. MTA позволяет игрокам со всего мира играть друг против друга в режиме онлайн. Как написано в Wikipedia, особенностью игры является «оптимизированный код с наименьшим количеством сбоев». Что же, давайте посмотрим, что скажет анализатор кода.


    Введение


    В этот раз, я решил не включать в статью диагностические сообщения, которые анализатор PVS-Studio выдаёт на подозрительные строки. Все равно я даю пояснения к фрагментам кода. Если интересно узнать, в какой именно строке найдена ошибка и какое диагностическое сообщение выдал анализатор, то это можно посмотреть в файле mtasa-review.txt.

    Когда я просматривал проект, я выписывал в файл mtasa-review.txt фрагменты кода, которые мне показались подозрительными. Позже, основываясь на нём, я написал эту статью.

    Важно. В файл попали только те фрагменты код, которые не понравились лично мне. Я не участвую в разработке MTA и не представляю, как и что в ней работает. Поэтому, наверняка я местами ошибся: включил в список корректный код и пропустил настоящие ошибки. А где-то вообще поленился и не стал описывать не совсем правильный вызов функции printf(). Прошу разработчиков из MTA Team не полагаться на этот текст и самостоятельно проверить проект. Проект достаточно большой и демонстрационной версии не хватит для полноценной проверки. Однако мы поддерживаем бесплатные open-source проекты. Напишите нам, и мы договоримся на тему бесплатной версии PVS-Studio.

    Итак, игра Multi Theft Auto является open-source проектом, написанным на языке Си/Си++:

    Для проверки я использовал анализатор PVS-Studio 5.05:


    Посмотрим теперь, что смог найти анализатор PVS-Studio в этой игре. Ошибок не так уж и много. Причём большинство из них содержится в редко используемых частях программы (обработчики ошибок). Это не удивительно. Большинство ошибок исправляется другими, более медленными и дорогими методами. Правильное использование статического анализа — регулярный запуск. Например, анализатор PVS-Studio умеет запускаться для только что изменённых и скомпилированных файлов (см. режим инкрементального анализа). Так разработчик сразу находит и устраняет многие ошибки и опечатки. Это во много раз быстрее и дешевле, чем обнаружить эти ошибки при тестировании. Подробнее эта тема рассматривалась в статье "Лев Толстой и статический анализ кода". Хорошая статья. Рекомендую почитать вводную часть, чтобы понять идеологию использования таких инструментов, как PVS-Studio.

    Странные цвета


    // c3dmarkersa.cpp
    SColor C3DMarkerSA::GetColor()
    {
      DEBUG_TRACE("RGBA C3DMarkerSA::GetColor()");
      // From ABGR
      unsigned long ulABGR = this->GetInterface()->rwColour;
      SColor color;
      color.A = ( ulABGR >> 24 ) && 0xff;
      color.B = ( ulABGR >> 16 ) && 0xff;
      color.G = ( ulABGR >> 8 ) && 0xff;
      color.R = ulABGR && 0xff;
      return color;
    }

    Случайно, вместо '&' используется '&&'. В результате от цвета остаются рожки и ножки в виде нуля или единицы.

    Идентичную беду можно наблюдать в файле «ccheckpointsa.cpp».

    Другая беда с цветопередачей.
    // cchatechopacket.h
    class CChatEchoPacket : public CPacket
    {
      ....
      inline void SetColor( unsigned char ucRed,
                            unsigned char ucGreen,
                            unsigned char ucBlue )
      { m_ucRed = ucRed; m_ucGreen = ucGreen; m_ucRed = ucRed; };
      ....
    }

    Два раза копируется красный цвет, но не копируется синий. Правленый код, должен быть таким:
    { m_ucRed = ucRed; m_ucGreen = ucGreen; m_ucBlue = ucBlue; };

    Идентичная проблема имеется в файле cdebugechopacket.h.

    Вообще, целый ряд ошибок в игре дублируется в двух файлах. Как мне кажется, один из файлов относится к клиентской части, а второй к серверной. Чувствуется вся мощь технологии Copy-Paste :).

    Что-то не так с utf8


    // utf8.h
    int
    utf8_wctomb (unsigned char *dest, wchar_t wc, int dest_size)
    {
      if (!dest)
        return 0;
      int count;
      if (wc < 0x80)
        count = 1;
      else if (wc < 0x800)
        count = 2;
      else if (wc < 0x10000)
        count = 3;
      else if (wc < 0x200000)
        count = 4;
      else if (wc < 0x4000000)
        count = 5;
      else if (wc <= 0x7fffffff)
        count = 6;
      else
        return RET_ILSEQ;
      ....
    }

    Размер типа wchar_t в Windows составляет 2 байта. Диапазон его значений равен [0..65535]. Это значит, что сравнение с числами 0x10000, 0x200000, 0x4000000, 0x7fffffff не имеет смысла. Наверное, код должен был быть написан как-то иначе.

    Забытый break


    // cpackethandler.cpp
    void CPacketHandler::Packet_ServerDisconnected (....)
    {
      ....
      case ePlayerDisconnectType::BANNED_IP:
        strReason = _("Disconnected: You are banned.\nReason: %s");
        strErrorCode = _E("CD33");
        bitStream.ReadString ( strDuration );
      case ePlayerDisconnectType::BANNED_ACCOUNT:
        strReason = _("Disconnected: Account is banned.\nReason: %s");
        strErrorCode = _E("CD34");
        break;
      ....
    }

    В этом коде забыт оператор 'break'. В результате ситуация «BANNED_IP», обрабатывается так же, как и «BANNED_ACCOUNT».

    Странные проверки


    // cvehicleupgrades.cpp
    bool CVehicleUpgrades::IsUpgradeCompatible (
      unsigned short usUpgrade )
    {
      ....
      case 402: return ( us == 1009 || us == 1009 || us == 1010 );
      ....
    }

    Переменная два раза сравнивается с числом 1009. Чуть ниже можно найти ещё идентичное двойное сравнение.

    Следующее подозрительное сравнение:
    // cclientplayervoice.h
    bool IsTempoChanged(void)
    { 
      return m_fSampleRate != 0.0f ||
             m_fSampleRate != 0.0f ||
             m_fTempo != 0.0f;
    }

    Эта же ошибка скопирована в файл cclientsound.h.

    Разыменовывание нулевого указателя


    // cgame.cpp
    void CGame::Packet_PlayerJoinData(CPlayerJoinDataPacket& Packet)
    {
      ....
      // Add the player
      CPlayer* pPlayer = m_pPlayerManager->Create (....);
      if ( pPlayer )
      {
        ....
      }
      else
      {
        // Tell the console
        CLogger::LogPrintf(
          "CONNECT: %s failed to connect "
          "(Player Element Could not be created.)\n",
          pPlayer->GetSourceIP() );
      }
      ....
    }

    Если не удалось создать объект «игрок», то программа пытается напечатать соответствующую информацию в консоль. Но не удачно. Плохая идея использовать нулевой указатель, вызывая функцию «pPlayer->GetSourceIP()».

    Другой нулевой указатель разыменовывается здесь:
    // clientcommands.cpp
    void COMMAND_MessageTarget ( const char* szCmdLine )
    {
      if ( !(szCmdLine || szCmdLine[0]) )
        return;
      ....
    }

    Если указатель szCmdLine равен нулю, то произойдет его разыменование.

    Скорее всего, здесь должно быть так:
    if ( !(szCmdLine && szCmdLine[0]) )

    Больше всего, мне понравился вот этот фрагмент кода:
    // cdirect3ddata.cpp
    void CDirect3DData::GetTransform (....) 
    {
      switch ( dwRequestedMatrix )
      {
        case D3DTS_VIEW:
          memcpy (pMatrixOut, &m_mViewMatrix, sizeof(D3DMATRIX));
          break;
        case D3DTS_PROJECTION:
          memcpy (pMatrixOut, &m_mProjMatrix, sizeof(D3DMATRIX));
          break;
        case D3DTS_WORLD:
          memcpy (pMatrixOut, &m_mWorldMatrix, sizeof(D3DMATRIX));
          break;
        default:
          // Zero out the structure for the user.
          memcpy (pMatrixOut, 0, sizeof ( D3DMATRIX ) );
          break;
      }
      ....
    }

    Красивый Copy-Paste. Вместо последней функции memcpy() должна вызываться функция memset().

    Неочищенные массивы


    Есть целый ряд ошибок, связанный с неочищенными массивами. Ошибки можно разделить на две категории. Первая — не удалены элементы. Вторая — не во все элементы массива записаны нулевые значения.

    Неудалённые элементы


    // cperfstat.functiontiming.cpp
    std::map < SString, SFunctionTimingInfo > m_TimingMap;
    
    void CPerfStatFunctionTimingImpl::DoPulse ( void )
    {
      ....
      // Do nothing if not active
      if ( !m_bIsActive )
      {
        m_TimingMap.empty ();
        return;
      }
      ....
    }

    Функция empty() проверяет, содержит контейнер элементы или нет. Чтобы удалить элементы из контейнера 'm_TimingMap', следовало вызвать функцию clear().

    Следующий пример:
    // cclientcolsphere.cpp
    void CreateSphereFaces (
      std::vector < SFace >& faceList, int iIterations )
    {
      int numFaces = (int)( pow ( 4.0, iIterations ) * 8 );
      faceList.empty ();
      faceList.reserve ( numFaces );
      ....
    }

    Ещё несколько таких ошибок есть в файле cresource.cpp.

    Примечание. Если кто-то пропустил начало статьи и решил читать с середины: где находятся эта и остальные шибки, можно узнать в файле mtasa-review.txt.

    Теперь об ошибках заполнения нулями


    // crashhandler.cpp
    LPCTSTR __stdcall GetFaultReason(EXCEPTION_POINTERS * pExPtrs)
    {
      ....
      PIMAGEHLP_SYMBOL pSym = (PIMAGEHLP_SYMBOL)&g_stSymbol ;
      FillMemory ( pSym , NULL , SYM_BUFF_SIZE ) ;
      ....
    }

    На первый взгляд всё хорошо. Вот только FillMemory() не будет иметь никакого эффекта. FillMemory() и memset() это не одно и тоже. Вот смотрите:
    #define RtlFillMemory(Destination,Length,Fill) \
      memset((Destination),(Fill),(Length))
    #define FillMemory RtlFillMemory


    Второй и третий аргумент меняются местами. По этому, правильно будет так:

    FillMemory ( pSym , SYM_BUFF_SIZE, 0 ) ;


    Аналогичная путаница существует в файле ccrashhandlerapi.cpp.

    И последний фрагмент кода на рассматриваемую тему. Здесь очищается только один байт.
    // hash.hpp
    unsigned char m_buffer[64];
    void CMD5Hasher::Finalize ( void )
    {
      ....
      // Zeroize sensitive information
      memset ( m_buffer, 0, sizeof (*m_buffer) );
      ....
    }

    Звездочка '*' является лишней. Должно быть написано «sizeof (m_buffer)».

    Неинициализированная переменная


    // ceguiwindow.cpp
    Vector2 Window::windowToScreen(const UVector2& vec) const
    {
      Vector2 base = d_parent ?
        d_parent->windowToScreen(base) + getAbsolutePosition() :
        getAbsolutePosition();
      ....
    }


    Переменная 'base' используется для инициализации самой себя. Ещё одна такая ошибка есть несколькими строчками ниже.

    Выход за границу массива


    // cjoystickmanager.cpp
    struct
    {
      bool    bEnabled;
      long    lMax;
      long    lMin;
      DWORD   dwType;
    } axis[7];
    
    bool CJoystickManager::IsXInputDeviceAttached ( void )
    {
      ....
      m_DevInfo.axis[6].bEnabled = 0;
      m_DevInfo.axis[7].bEnabled = 0;
      ....
    }

    Последняя строчка «m_DevInfo.axis[7].bEnabled = 0;» лишняя.

    Другая ошибка
    // cwatermanagersa.cpp
    class CWaterPolySAInterface
    {
    public:
      WORD m_wVertexIDs[3];
    };
    
    CWaterPoly* CWaterManagerSA::CreateQuad ( const CVector& vecBL, const CVector& vecBR, const CVector& vecTL, const CVector& vecTR, bool bShallow )
    {
      ....
      pInterface->m_wVertexIDs [ 0 ] = pV1->GetID ();
      pInterface->m_wVertexIDs [ 1 ] = pV2->GetID ();
      pInterface->m_wVertexIDs [ 2 ] = pV3->GetID ();
      pInterface->m_wVertexIDs [ 3 ] = pV4->GetID ();
      ....
    }

    И ещё одна:
    // cmainmenu.cpp
    #define CORE_MTA_NEWS_ITEMS 3
    
    CGUILabel* m_pNewsItemLabels[CORE_MTA_NEWS_ITEMS];
    CGUILabel* m_pNewsItemShadowLabels[CORE_MTA_NEWS_ITEMS];
    
    void CMainMenu::SetNewsHeadline (....)
    {
      ....
      for ( char i=0; i <= CORE_MTA_NEWS_ITEMS; i++ )
      {
        m_pNewsItemLabels[ i ]->SetFont ( szFontName );
        m_pNewsItemShadowLabels[ i ]->SetFont ( szFontName );
        ....
      }
      ....
    }

    Ещё, как минимум одна ошибка выхода за границы массива есть в файле cpoolssa.cpp. Но описывать её в статье я не стал. Получается длинноватый пример, а как сделать коротко и понятно, я не знаю. Эту и другие ошибки, как я уже говорил можно посмотреть в более полном отчёте.

    Пропущено слово 'throw'


    // fallistheader.cpp
    ListHeaderSegment*
    FalagardListHeader::createNewSegment(const String& name) const
    {
      if (d_segmentWidgetType.empty())
      {
        InvalidRequestException(
          "FalagardListHeader::createNewSegment - "
          "Segment widget type has not been set!");
      }
      return ....;
    }

    Здесь должно было быть «throw InvalidRequestException(....)».

    Другой фрагмент кода.
    // ceguistring.cpp 
    bool String::grow(size_type new_size)
    {
      // check for too big
      if (max_size() <= new_size)
        std::length_error(
          "Resulting CEGUI::String would be too big");
      ....
    }

    Должно быть: throw std::length_error(....).

    Ой: free(new T[n])


    // cresourcechecker.cpp
    int CResourceChecker::ReplaceFilesInZIP(....)
    {
      ....
      // Load file into a buffer
      buf = new char[ ulLength ];
      if ( fread ( buf, 1, ulLength, pFile ) != ulLength )
      {
        free( buf );
        buf = NULL;
      }
      ....
    
    }

    Память выделяется с помощью оператора 'new'. А освободить её пытаются с помощью функции free(). Результат непредсказуем.

    Всегда истинные/ложные условия


    // cproxydirect3ddevice9.cpp
    #define D3DCLEAR_ZBUFFER 0x00000002l
    HRESULT CProxyDirect3DDevice9::Clear(....)
    {
      if ( Flags | D3DCLEAR_ZBUFFER )
        CGraphics::GetSingleton().
          GetRenderItemManager()->SaveReadableDepthBuffer();
      ....
    }

    Программист хотел проверить определенный бит в переменной Flag. Из-за опечатки, вместо операции '&' он использовал операцию '|'. В результате, условие всегда выполняется.

    Аналогичная путаница есть в файле cvehiclesa.cpp.

    Следующая ошибка с проверкой: unsigned_value < 0.
    // crenderitem.effectcloner.cpp
    unsigned long long Get ( void );
    
    void CEffectClonerImpl::MaybeTidyUp ( void )
    {
      ....
      if ( m_TidyupTimer.Get () < 0 )
        return;
      ....
    }

    Функция Get() возвращает значение беззнакового типа 'unsigned long long'. Значит проверка «m_TidyupTimer.Get () < 0» не имеет смысла. Другие ошибки этой разновидности в встречаются в файлах: csettings.cpp, cmultiplayersa_1.3.cpp, cvehiclerpcs.cpp.

    Это может работать, но лучше провести рефакторинг


    Многие сообщения, выданные PVS-Studio, диагностируют ошибки, которые, скорее всего, никак не проявят себя. Я не люблю писать про такие ошибки. Это не интересно. Приведу только несколько примеров.

    // cluaacldefs.cpp
    int CLuaACLDefs::aclListRights ( lua_State* luaVM )
    {
      char szRightName [128];
      ....
      strncat ( szRightName, (*iter)->GetRightName (), 128 );
      ....
    }

    Третий аргумент функции strncat() указывает не размер буфера, а сколько ещё символов в него можно поместить. Теоретически, здесь возможно переполнение буфера. На практике, скорее всего это никогда не произойдёт. Подробнее про данный тип ошибки, можно почитать в описании диагностики V645.

    Ещё один пример.
    // cscreenshot.cpp
    void CScreenShot::BeginSave (....)
    {
      ....
      HANDLE hThread = CreateThread (
        NULL,
        0,
        (LPTHREAD_START_ROUTINE)CScreenShot::ThreadProc,
        NULL,
        CREATE_SUSPENDED,
        NULL );
      ....
    }

    Во многих местах игры используются функции CreateThread()/ExitThread(). Как правило, это не совсем верно. Следует использовать функции _beginthreadex()/_endthreadex(). Подробнее про это, можно узнать из описания диагностики V513.

    Надо где-то остановиться


    Я описал далеко не все из недочетов, которые я заметил. Однако, пора останавливаться. Статья уже и так достаточно велика. С другими ошибками, вы можете познакомиться в файле mtasa-review.txt.

    Например, там есть следующие типы ошибок, отсутствующие в статье:
    • одинаковые ветки в условном операторе: if () { aa } else { aa };
    • проверка указателя, который возвращает оператор 'new', на равенство нулю: p = new T; if (!p) { aa };
    • плохой способ использования #pragma для подавления предупреждений (не используется push/pop);
    • в классах есть виртуальные функции, но нет виртуального деструктора;
    • указатель в начале разыменовывается, а уже затем проверяется на равенство нулю;
    • повторяющиеся условия: if (X) { if (X) { aa } };
    • прочее.


    Заключение


    Анализатор PVS-Studio может эффективно быть использован для раннего устранения многих ошибок, как в игровых проектах, так и в любых других. Алгоритмические ошибки он не найдёт (для этого нужен искусственный интеллект). Зато существенно время, которое бесполезно тратится на поиск глупых ошибок и опечаток. Программисты тратят на простые дефекты гораздо больше, чем думают. Даже в уже отлаженном и оттестированном коде, таких ошибок много. А при написании нового кода, таких ошибок исправляется в 10 раз больше.
    PVS-Studio
    Static Code Analysis for C, C++, C# and Java

    Comments 45

      +7
      Забыли в хвосте FAQ :D
      Как жаль, что на линупсе не юзабелен.
      Знаю кому посоветовать, настоятельно так посоветовать, а нечего…
        0
        А у вас есть в планах сделать его под линукс(и желательно консольным)?
          +20
          Вы приобретёте версию под Linux, или просто так спрашиваете?
            +3
            Для домашний вещей хватит и Valgrind (да не статический анализатор но хоть что-то) и LLVM можно подцепить. А вот для компаний которые занимаются разработкой софта под линукс было бы очень полезно иметь консольный вариант программы, так как его к любой IDE можно подцепить. Ну а цена от 5к евро для компании(игрушками которая занимается) думаю подъёмная.
            • UFO just landed and posted this here
                +11
                Linux мир привык к халяве. Причем, привыкли как люди, так и группы разработчиков. Ведь группы разработчиков состоят из тех же самых людей. :)

                Это плохо для таких компаний, как мы. Будет очень сложно продать продукт. Большинство компаний, занимающихся созданием бесплатного open-source, черпают доходы из других мест. В нашем случае, прихода денег c других направлений нет. Что продали, то и заработали.

                Не раз встречал на конференции людей, работающих, для примера в Intel. Они рассказывают, какую замечательную бесплатную open-source штуку делают. И как вообще, open-source полезен, как здорово, если все им будут заниматься и вообще они за мир во всем мире. При этом, в стороне остается вопрос, что им платят зарплату. Деньги на неё заработаны вовсе не его стараниями. Сидят такие разработчики на зарплате в Google, Intel,… и рассказывают в статьях, как здорово писать бесплатный open-source. И здорово, если другие разработчики им помогут. :)

                Это все замечательно. И я вовсе не против open-source и бесплатности. Но я то тут причём? Мне надо те только удовольствие от процесса создания программ получать, но ещё и деньги зарабатывать.
                  +1
                  ну строго говоря, у того же хамбл бамбл средний чек с линукс-юзера выше, чем с гвиндовс-юзера.
                  учитывая, что софт весьма специфический, а разработчиков на линукс не мало, в том числе и коммерческого closed-source, сложно оценивать рынок.
                  но если смотреть на массовость — то да, линукс не эффективен, продаж будет от винды процентов 10 максимум.
                    0
                    Intel наряду с open-source обычно продают и коммерческую версию, ну например тем кого GPL не устраивает или кого на работе вынуждают покупать с поддержкой. В качестве примера сходу — TBB. Ну и полно совсем не open-source продуктов которые делают те же программисты.

                    В вашем случае open-source вообще не вариант наверное — продукт можно использовать и никто никогда не узнает был использован платный продукт или open-source. А учитывая ваш ценник — многие смогут подавить угрызения совести достаточно легко. :) Но никто вас и не заставляет ваять open source продукт под линукс, как я уже писал тот же интел клепает коммерческие не open-source продукты под linux без проблем.

                    Вот лично мне вообще трудно понять зачем такой продукт на машине пользователей а не на сервере с jenkins'ом каким-нибудь. Нет я понимаю что кому-то оно нужно, но многих бы устроил и вариант запуска его только на сборочном сервере. Я не поленился зашел на ваш сайт и увидел что в доках описана какая-никакая интеграция с hudson(правда опять под неправославной виндой, но это можно пережить если пишешь мультиплатформенный продукт), но есть одно «но» — цена на 1 и 5 лицензий одна и та же и совсем не демократичная… Хотя не мне вам советовать какую цену назначать, но обычно всё же есть возможность купить одну-единственную лицензию дешевле чем 5.
                      0
                      А как вам такая вариация — CppCat? Это наш новый статический анализатор кода. Младший братишка.
                      –1
                      У линуксоидов есть деньги, сэкономленные на покупке ОС, которые есть куда потратить :)
                      Я использую платную IDE, к примеру.
                        +1
                        Не смешите. OEM Windows 8 стоит баксов 30. Много вы лицензионного софта накупите на эти деньги?
                          +1
                          Вот только OEM-версию какбе купить человеку нельзя.
                            0
                            Ошибаетесь, по лиц. соглашению теперь — можно.
                              0
                              одновременно с новым комьпьютером и только для установки на этот самый компьютер?
                                0
                                Windows 8 для сборщиков систем – Персональная лицензия

                                Каким образом можно использовать данное программное обеспечение?

                                Мы не продаем наше программное обеспечение или вашу копию – мы только лицензируем его. Согласно нашей лицензии, мы предоставляем вам право установить и запустить эту одну копию на одном компьютере (лицензированный компьютер), как операционную систему на компьютере, который вы собираете для личного использования, или как дополнительную операционную систему, работающую в локальной виртуальной машине или в отдельном разделе, при соблюдении ограничений, изложенных в пункте «Существуют ли ограничения в отношении данного программного обеспечения?» Лицензия предназначена только для одновременного использования одним лицом, и только если вы соблюдаете все условия настоящего соглашения. Данное программное обеспечение не лицензируется для использования в качестве серверного программного обеспечения или для предоставления удаленного доступа на коммерческой основе — поэтому вы не имеете право на использование данного программного обеспечения в сети несколькими пользователями одновременно. Дополнительные сведения об использовании программного обеспечения несколькими пользователями и виртуализации см. в Дополнительных условиях.


                                Как видите, правила слегка поменялись, теперь OEM можно ставить на любой компьютер, но только для личного пользования.
                                  0
                                  «который вы собираете для личного использования»
                                    0
                                    " или как дополнительную операционную систему, работающую в локальной виртуальной машине или в отдельном разделе"
                        +5
                        > Linux мир привык к халяве.

                        Индивидуальные люди покупают всякое. Я, например, под линуксом оплатил значительно больше софта чем под виндой (стим, донат).
                        В корпорациях нет никакой разницы линукс или винда.

                        С тем же успехом можно сказать что виндузятники привыкли к халяве потому что все всё пиратят.
                          +4
                          Какая, простите, дремучая чепуха. Посмотрите на список суперкомпьютеров. Сколько из них не на линуксе? И на процент серверов. Вся серьезная индустрия на нем, больше не на чем. Все остальное неизвестно будет завтра или нет, а линукс никуда не денется — его некому прикрыть или изменить до неузноваемости. И что они все к халяве привыкли? Ораклу расскажите. Тот же интеловский компилятор для линукса стоит денег если для коммерческого применения. Тот же матлаб прекрасно продается для линукса. Всегда хорошо дать людям оценить продукт даром. Продавайте поддержку, продавайте версию про, продавайте обычную версию для использования в коммерческих продуктах. Если ваш продукт хорошо анализирует С/С++ код его купят и для линукса, рынка там не меньше. Если он конечно чего-то стоит. Если он может принять участие в сревнованиях. Если вы способны его туда привести — к стартовой черте, хотя бы.
                            –1
                            Linux Мир привык к халяве.

                            Исправлено.

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

                            А заявления вроде этого, если они исходят от представителей какой-то компании, лично у меня вызывают в первую очередь желание никогда с ней не связываться.
                              +1
                              объявить о сборе средств

                              Даже не смешно.
                                –1
                                На kickstarter'е это работает. Не для всех проектов, наверное, но работает. =)
                                  0
                                  В смысле, оценить предварительно время изготовления.
                                  И выложить предзаказ.
                              0
                              Теперь есть вариант, который подойдет не только компаниям, но и для дома. Это продукт CppCat.
                              +8
                              У вас с линуксовой версией анализатора проблема курицы и яйца — вы не делаете, т.к. нет спроса, а спроса нет т.к. нельзя взять протестировать месяцок в живом реальном проекте и выдать своим менеджерам репорт, что вот, мол полезная вещь в проекте и надо брать. Вариант «попробуйте win версию» не подходит — пробовал как-то. У нас к примеру webkit для qnx и когда я начал только добавлять тысячи файлов в visual studio (в которой только и работает ваш анализатор) — он попросту захлебнулся и спустя то ли пол часа, то ли минут минут 40 он так и не подавал признаков жизни. До конфигурирования (а у нас штук 10 конфигураций) я так и не дошёл.

                              Linux мир привык к халяве

                              С таким взглядом на огромный потенциальный рынок — вы далеко не уедете. Коммерческих проектов на базе того же линукс — огромное количество. Да и линукс это только один из представителей огромнейшего *nix семейства, а если посчитать всё семейство (linux, *bsd, solaris, qnx, osx), то оно по масштабам внедрения коммерческих продуктов переплюнет весь win сегмент. Я понимаю, что ОЧЕНЬ сложно сделать поддержку всего этого зоопарка, но для меня ваша позиция смотрится, как отказ в инвестирование новых рынков, причём огромных рынков.
                                0
                                Вариант «попробуйте win версию» не подходит — пробовал как-то. У нас к примеру webkit для qnx и когда я начал только добавлять тысячи файлов в visual studio (в которой только и работает ваш анализатор)


                                Анализатор работает не только под Visual Studio. Под Visual Studio работает соответствующий этой IDE плагин, а непосредственно сам анализатор — это command-line утилита, которую можно интегрировать куда угодно, хоть в те же makefile'ы. На нашем сайте более подробно написано про это.
                                  0
                                  На тему PVS-Studio Standalone и Linux, возможно будет интересна вот эта новая заметка — "PVS-Studio теперь работает и без среды Visual Studio или C++Builder – проверяем препроцессированные файлы от чего угодно".
                                +8
                                Ответ тут: www.viva64.com/ru/b/0132/#ID0EUAAC
                                Но мне кажется, что авторам стоит сделать Linux-версию лишь для того, чтобы не тратить время, отвечая на этот вопрос в каждом топике (:
                                • UFO just landed and posted this here
                                    0
                                    Свершилось: PVS-Studio для Linux.
                                    0
                                    Прям совпало с выходом Официальное Геймплейное Видео GTA Online
                                      +4
                                      Размер типа wchar_t в Windows составляет 2 байта.


                                      Функция utf8_wctomb скопирована из каких-то линуксовых библиотек. А там wchar_t — 4 байта, и функция должна остаться работоспособной даже при таком условии. Так что я расцениваю описанное в статье предупреждение как ложное срабатывание.
                                        0
                                        Да. Но вот у меня нет вовсе уверенности, что это будет правильно работать. Так что такой код лучше посмотреть.
                                          0
                                          компилятор (любой нормальный) все эти ветки выкинет.
                                        0
                                        А для индивидуальных разработчиков Вы подобных продуктов не производите?
                                        +2
                                        Добрый день,

                                        являюсь мэйтенером нескольких небольших OpenSource проектов.
                                        Хотел бы у Вас спросить: не планируете ли вы сделать сервис проверки OpenSource проектов как это сделали Coverity?
                                        Для примера: мой работодатель был очень доволен проверкой Coverity нашего OS проекта и приобрёл коммерческий пакет для проверки других своих закрытых проектов.
                                        Я бы с радостью воспользовался таким сервисом и конечно же упомянул Ваш проект в описании и рекомендовал своим работадателям.
                                          +1
                                          Вы всегда может нам написать и попросить бесплатную лицензию для open source проектов.
                                            +1
                                            К сожалению, не планируем. Это много работы, а мы маленькие. Да, это хороший метод рекламы. Но даже тот-же Coverity делает это не из-за неё. Это уже потом они сообразили, что так можно заодно порекламироваться. И уж тем более не из-за любви к OS. У них есть заказ с грантами от министерства обороны на проверку открытых проектов. Если нас бы так кто поддержал, мы бы тоже с радостью всем всё проверяли. :)

                                            К счастью PVS-Studio легко попробовать как для OS так и для закрытого проекта.
                                            +5
                                            Из забавного. В этот раз я не отписал разработчикам. :) Я не прошел квест. Я не увидел, где зарегистрироваться для доступа к bug tracker. Хотел написать на форум. Но там тоже не смог зарегистрироваться. Видимо я стал роботом. :-(
                                              0
                                              Всё, подсказали. Спасибо. Оставил информацию.
                                              +2
                                              Хотел поблагодарить вас, от лица команды разработчиков MTA, за вашу статью на Хабре и проведенный анализ в целом, а так же отдельное спасибо за заявку у нас на баг трекере! ;)
                                              Мы уже закоммитили исправления найденных ошибок в транк.

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

                                              Наш проект развивается уже на протяжении 10 лет, усилиями энтузиастов разного возраста и уровня знаний, поэтому можно заметить недостатки как в логике, так и в структуре кода, собственно и я впервые приложил свою руку к проекту еще в школьные годы. Очень часто проглядывается стиль С в С++ коде, например сравнения указателей с NULL после оператора new, вместо обработки исключения, забывая что это не то же самое что malloc, или освобождение объектов функцией free. Но тем не менее мы не забрасываем свой код, даже не смотря на то что он уже морально устарел, и пытаемся исправить свои ошибки по мере возможностей.

                                              Собственно, PVS-Studio оказался достаточно полезным для нас, остается лишь пожелать вам успехов и дальнейшего развития!
                                                +1
                                                Спасибо за отзыв!

                                              Only users with full accounts can post comments. Log in, please.