X ray engine не работает делать. X-Ray - игровой движок серии STALKER

Большое количество пользователей продуктов компании Microsoft сообщает о потере активации Windows 10 и превращении Pro-версии в Домашнюю. Пользователям приходит уведомление об истекшем ключе, а при попытках реактивации выбивает ошибку 0x803fa067 для Windows 10. Как исправить неполадки и запустить систему – об этом далее в статье.

Причины сбоев

Microsoft на стандартных условиях предлагает ввод ключей активации для подтверждения подлинности, а также правильного использования установленной версии Windows.

Ошибка активации 0x803fa067 Windows 10

Ошибка 0x803fa067 при активации Windows 10 может возникать по нескольким причинам:

Интересно знать! Компания официально признала наличие проблемы с сервером активации Pro версий (0x803fa067) для . Жалобы поступали от пользователей со всего мира: Кореи, Японии и жителей прочих стран.

Использование средства для устранения ошибок

Функция по исправлению неполадок доступна только в том случае, если копия Виндовс 10 (1607 и выше версии) еще не была активирована. Данный сервис позволит устранить имеющиеся неполадки с активацией. Чтобы воспользоваться функционалом, пользователь должен быть администратором.


Запуск устранения неполадок или повторный ввод лицензионного ключа повторно активирует систему

Для запуска средства устранения неполадок выполните следующие действия:

      1. Нажмите на кнопку «Пуск».
      2. Перейдите в раздел «Параметры».
      3. Далее выбирайте «Обновления и безопасность».
      4. И укажите пункт «Активация».
      5. После нажимайте на строку «Устранение неполадок».

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


    Активация Windows 10

    Важно! Если при установке Windows 10 возникает ошибка 0x803fa067, может потребоваться подтверждение о легальном приобретении продукта: сканы чеков на покупку, наклеек и копий писем, свидетельствующих о переписке с магазинами электронной дистрибуции.

    Компания Microsoft сообщает, что возникновение кода ошибки 0x803fa067 при активации Виндовс 10, может быть связано с тем, что в момент бесплатного обновления была установлена не самая последняя версия.

    Решение ошибки 0x803fa067 при активации Windows10

    Для активации Windows 10 необходимо подключение к Интернету. Чтобы диагностировать и знать, как исправить ошибку 0x803fa067 в Windows 10, следует выполнить ряд последовательных действий:


    Если же выше приведенные действия не помогают, обратитесь в

Большое количество пользователей продуктов компании Microsoft сообщает о потере активации Windows 10 и превращении Pro-версии в Домашнюю. Пользователям приходит уведомление об истекшем ключе, а при попытках реактивации выбивает ошибку 0x803fa067 для Windows 10. Как исправить неполадки и запустить систему – об этом далее в статье.

Причины сбоев

Microsoft на стандартных условиях предлагает ввод ключей активации для подтверждения подлинности, а также правильного использования установленной версии Windows.

Ошибка активации 0x803fa067 Windows 10

Ошибка 0x803fa067 при активации Windows 10 может возникать по нескольким причинам:

Интересно знать! Компания официально признала наличие проблемы с сервером активации Pro версий (0x803fa067) для Windows 10 . Жалобы поступали от пользователей со всего мира: Кореи, Японии и жителей прочих стран.

Использование средства для устранения ошибок

Функция по исправлению неполадок доступна только в том случае, если копия Виндовс 10 (1607 и выше версии) еще не была активирована. Данный сервис позволит устранить имеющиеся неполадки с активацией. Чтобы воспользоваться функционалом, пользователь должен быть администратором.


Запуск устранения неполадок или повторный ввод лицензионного ключа повторно активирует систему

Для запуска средства устранения неполадок выполните следующие действия:

      1. Нажмите на кнопку «Пуск».
      2. Перейдите в раздел «Параметры».
      3. Далее выбирайте «Обновления и безопасность».
      4. И укажите пункт «Активация».
      5. После нажимайте на строку «Устранение неполадок».

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


    Активация Windows 10

    Важно! Если при установке Windows 10 возникает ошибка 0x803fa067, может потребоваться подтверждение о легальном приобретении продукта: сканы чеков на покупку, наклеек и копий писем, свидетельствующих о переписке с магазинами электронной дистрибуции.

    Компания Microsoft сообщает, что возникновение кода ошибки 0x803fa067 при активации Виндовс 10, может быть связано с тем, что в момент бесплатного обновления была установлена не самая последняя версия.

    Решение ошибки 0x803fa067 при активации Windows10

    Для активации Windows 10 необходимо подключение к Интернету. Чтобы диагностировать и знать, как исправить ошибку 0x803fa067 в Windows 10, следует выполнить ряд последовательных действий:


    Если же выше приведенные действия не помогают, обратитесь в

X-Ray был создан украинской компанией GSC GameWorld для игры S.T.A.L.K.E.R.: Тень Чернобыля. Движок включает рендер с поддержкой DirectX 8.1/9.0c/10/10.1/11, физический и звуковой движки, мультиплеер и систему искусственного интеллекта A-Life. Впоследствии компания создавала движок версии 2.0 для своей новой игры, но разработка была прекращена и исходные коды утекли в сеть.

Проект вместе со всеми его зависимостями легко собирается в Visual Studio 2015. Для проверки использовался исходный код движка версии 1.6 из репозитория на GitHub и статический анализатор кода PVS-Studio 6.04, загрузить который можно по ссылке .

Copy-paste

Для начала рассмотрим ошибки, связанные с копированием кода. Сценарий их возникновения в разных случаях обычно похож: скопировали код, поменяли часть переменных, а несколько - забыли. Такие ошибки могут быстро распространяться по кодовой базе, и без статического анализатора их очень легко пропустить.

MxMatrix& MxQuadric::homogeneous(MxMatrix& H) const { .... unsigned int i, j; for(i=0; iПредупреждение PVS-Studio : V533 It is likely that a wrong variable is being incremented inside the "for" operator. Consider reviewing "i". mxqmetric.cpp 76

Анализатор обнаружил, что во вложенном цикле for инкрементируется переменная i , а проверяется переменная j , что приводит к бесконечному циклу. Скорее всего, при копировании её просто забыли поменять.
void CBaseMonster::settings_read(CInifile const * ini, LPCSTR section, SMonsterSettings &data) { .... if (ini->line_exist(ppi_section,"color_base")) sscanf(ini->r_string(ppi_section,"color_base"), "%f,%f,%f", &data.m_attack_effector.ppi.color_base.r, &data.m_attack_effector.ppi.color_base.g, &data.m_attack_effector.ppi.color_base.b); if (ini->line_exist(ppi_section,"color_base")) sscanf(ini->r_string(ppi_section,"color_gray"), "%f,%f,%f", &data.m_attack_effector.ppi.color_gray.r, &data.m_attack_effector.ppi.color_gray.g, &data.m_attack_effector.ppi.color_gray.b); if (ini->line_exist(ppi_section,"color_base")) sscanf(ini->r_string(ppi_section,"color_add"), "%f,%f,%f", &data.m_attack_effector.ppi.color_add.r, &data.m_attack_effector.ppi.color_add.g, &data.m_attack_effector.ppi.color_add.b); .... }
Предупреждения PVS-Studio :

  • V581 The conditional expressions of the "if" operators situated alongside each other are identical. Check lines: 445, 447. base_monster_startup.cpp 447
  • V581 The conditional expressions of the "if" operators situated alongside each other are identical. Check lines: 447, 449. base_monster_startup.cpp 449
В данном фрагменте используются подряд несколько одинаковых условных выражений. Очевидно, что необходимо заменить color_base на color_gray и color_add в соответствии с кодом в теле if ветви.
/* process a single statement */ static void ProcessStatement(char *buff, int len) { .... if (strncmp(buff,"\\pauthr\\",8) == 0) { ProcessPlayerAuth(buff, len); } else if (strncmp(buff,"\\getpidr\\",9) == 0) { ProcessGetPid(buff, len); } else if (strncmp(buff,"\\getpidr\\",9) == 0) { ProcessGetPid(buff, len); } else if (strncmp(buff,"\\getpdr\\",8) == 0) { ProcessGetData(buff, len); } else if (strncmp(buff,"\\setpdr\\",8) == 0) { ProcessSetData(buff, len); } }
Предупреждение PVS-Studio : V517 The use of "if (A) {...} else if (A) {...}" pattern was detected. There is a probability of logical error presence. Check lines: 1502, 1505. gstats.c 1502

Как и в предыдущем примере, здесь используются два одинаковых условия (strncmp(buff,"\\getpidr\\",9) == 0 ). Сложно сказать наверняка, является ли это ошибкой или просто недостижимым кодом, но на это точно стоит обратить внимание. Возможно, что здесь должны быть блоки с getpidr /setpidr по аналогии с getpdr /setpdr .
class RGBAMipMappedCubeMap { .... size_t height() const { return cubeFaces.height(); } size_t width() const { return cubeFaces.height(); } .... };
Предупреждение PVS-Studio : V524 It is odd that the body of "width" function is fully equivalent to the body of "height" function. tpixel.h 1090

Методы height() и width() имеют одинаковое тело. Учитывая, что вычисляются размеры граней куба, возможно, ошибки здесь нет. Но лучше переписать метод width() следующим образом:
size_t width() const { return cubeFaces.width(); }

Неправильное использование C++

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

Template struct _matrix33 { public: typedef _matrix33Self; typedef Self& SelfRef; .... IC SelfRef sMTxV(Tvector& R, float s1, const Tvector& V1) const { R.x = s1*(m * V1.x + m * V1.y + m * V1.z); R.y = s1*(m * V1.x + m * V1.y + m * V1.z); R.z = s1*(m * V1.x + m * V1.y + m * V1.z); } .... }
Предупреждение PVS-Studio : V591 Non-void function should return a value. _matrix33.h 435

В конце метода пропущен return *this . По стандарту подобный код приведёт к неопределённому поведению. Так как возвращаемое значение является ссылкой, это, скорее всего, приведёт к падению программы при попытке обратиться к возвращаемому значению.
ETOOLS_API int __stdcall ogg_enc(....) { .... FILE *in, *out = NULL; .... input_format *format; .... in = fopen(in_fn, "rb"); if(in == NULL) return 0; format = open_audio_file(in, &enc_opts); if(!format){ fclose(in); return 0; }; out = fopen(out_fn, "wb"); if(out == NULL){ fclose(out); return 0; } .... }
Предупреждение PVS-Studio : V575 The null pointer is passed into "fclose" function. Inspect the first argument. ogg_enc.cpp 47

Довольно интересный пример. Анализатор обнаружил, что аргумент в вызове fclose равен nullptr , что делает вызов функции бессмысленным. Можно предположить, что должны были закрыть поток in.
void NVI_Image::ABGR8_To_ARGB8() { // swaps RGB for all pixels assert(IsDataValid()); assert(GetBytesPerPixel() == 4); UINT hxw = GetNumPixels(); for (UINT i = 0; i < hxw; i++) { DWORD col; GetPixel_ARGB8(&col, i); DWORD a = (col >> 24) && 0x000000FF; DWORD b = (col >> 16) && 0x000000FF; DWORD g = (col >> 8) && 0x000000FF; DWORD r = (col >> 0) && 0x000000FF; col = (a << 24) | (r << 16) | (g << 8) | b; SetPixel_ARGB8(i, col); } }
Предупреждения PVS-Studio:

  • V560 A part of conditional expression is always true: 0x000000FF. nvi_image.cpp 170
  • V560 A part of conditional expression is always true: 0x000000FF. nvi_image.cpp 171
  • V560 A part of conditional expression is always true: 0x000000FF. nvi_image.cpp 172
  • V560 A part of conditional expression is always true: 0x000000FF. nvi_image.cpp 173
В данном участке кода перепутаны логические и битовые операции. Результат будет не таким, какого ожидал программист: col будет всегда равен 0x01010101 независимо от входных данных.

Правильный вариант:
DWORD a = (col >> 24) & 0x000000FF; DWORD b = (col >> 16) & 0x000000FF; DWORD g = (col >> 8) & 0x000000FF; DWORD r = (col >> 0) & 0x000000FF;
Ещё один пример странного кода:
VertexCache::VertexCache() { VertexCache(16); }
Предупреждение PVS-Studio : V603 The object was created but it is not being used. If you wish to call constructor, "this->VertexCache::VertexCache(....)" should be used. vertexcache.cpp 6

Вместо вызова одного конструктора из другого для инициализации экземпляра будет создан и тут же уничтожен новый объект типа VertexCache . В результате члены создаваемого объекта останутся непроинициализированными.
BOOL CActor::net_Spawn(CSE_Abstract* DC) { .... m_States.empty(); .... }
Предупреждение PVS-Studio : V530 The return value of function "empty" is required to be utilized. actor_network.cpp 657

Анализатор предупреждает, что возвращаемое функцией значение не используется. Похоже, что программист перепутал методы empty() и clear() : empty() не очищает массив, а проверяет, является ли он пустым.

Такие ошибки нередко встречаются в различных проектах. Проблема в том, что имя empty() не очевидно: некоторые воспринимают его как действие - удаление. Для того, чтобы подобной неоднозначности не возникало лучше добавлять глаголы has, is к началу метода: действительно, isEmpty() с clear() сложно перепутать.

Похожее предупреждение:

V530 The return value of function "unique" is required to be utilized. uidragdroplistex.cpp 780
size_t xrDebug::BuildStackTrace(EXCEPTION_POINTERS* exPtrs, char *buffer, size_t capacity, size_t lineCapacity) { memset(buffer, capacity*lineCapacity, 0); .... }
Предупреждение PVS-Studio : V575 The "memset" function processes "0" elements. Inspect the third argument. xrdebug.cpp 104

При вызове memset аргументы перепутали местами и в итоге буфер не обнуляется, как изначально задумывалось. Подобная ошибка может жить в проекте очень долго, так как её очень трудно обнаружить. В таких местах на выручку программисту приходит статический анализатор.

Корректное использование memset :
memset(buffer, 0, capacity*lineCapacity);
Следующая ошибка связана с неправильно составленным логическим выражением.
void configs_dumper::dumper_thread(void* my_ptr) { .... DWORD wait_result = WaitForSingleObject(this_ptr->m_make_start_event, INFINITE); while (wait_result != WAIT_ABANDONED) || (wait_result != WAIT_FAILED)) .... }
Предупреждение PVS-Studio : V547 Expression is always true. Probably the "&&" operator should be used here. configs_dumper.cpp 262

Выражения вида "x != a || x != b" всегда являются истинным. Вероятнее всего вместо оператора || подразумевался оператор &&.

Подробнее об ошибках в логических выражениях можно прочитать в статье "Логические выражения в C/C++. Как ошибаются профессионалы ".
void SBoneProtections::reload(const shared_str& bone_sect, IKinematics* kinematics) { .... CInifile::Sect &protections = pSettings->r_section(bone_sect); for (CInifile::SectCIt i=protections.Data.begin(); protections.Data.end() != i; ++i) { string256 buffer; BoneProtection BP; .... BP.BonePassBullet = (BOOL) (atoi(_GetItem(i->second.c_str(), 2, buffer))>0.5f); .... } }
Предупреждение PVS-Studio : V674 The "0.5f" literal of the "float" type is compared to a value of the "int" type. boneprotections.cpp 54

Анализатор обнаружил сравнение целочисленного значения с вещественной константой. Возможно, что здесь по аналогии должна была использоваться функция atof , а не atoi , в другом случае стоит переписать это сравнение, чтобы оно не выглядело подозрительно. Однако сказать наверняка, является ли этот пример ошибочным или нет, может только разработчик, писавший его.
class IGameObject: public virtual IFactoryObject, public virtual ISpatial, public virtual ISheduled, public virtual IRenderable, public virtual ICollidable { public: .... virtual u16 ID() const = 0; .... } BOOL CBulletManager::test_callback(const collide::ray_defs& rd, IGameObject* object, LPVOID params) { bullet_test_callback_data* pData = (bullet_test_callback_data*)params; SBullet* bullet = pData->pBullet; if((object->ID() == bullet->parent_id) && (bullet->fly_distflags.ricochet_was)) return FALSE; BOOL bRes = TRUE; if (object){ .... } return bRes; }
Предупреждение PVS-Studio : V595 The "object" pointer was utilized before it was verified against nullptr. Check lines: 42, 47. level_bullet_manager_firetrace.cpp 42

Проверка указателя object на равенство nullptr идёт после того, как разыменовали object->ID() . В случае, когда object равен nullptr, это приведёт к падению программы.
#ifdef _EDITOR BOOL WINAPI DllEntryPoint(....) #else BOOL WINAPI DllMain(....) #endif { switch (ul_reason_for_call) { .... case DLL_THREAD_ATTACH: if (!strstr(GetCommandLine(), "-editor")) CoInitializeEx(NULL, COINIT_MULTITHREADED); timeBeginPeriod(1); break; .... } return TRUE; }
Предупреждение PVS-Studio : V718 The "CoInitializeEx" function should not be called from "DllMain" function. xrcore.cpp 205

В теле DllMain нельзя использовать часть WinAPI функций, включая CoInitializeEx. Убедиться в этом можно, прочитав документацию на MSDN . Нельзя дать какой-то однозначный совет, как стоит переписать эту функцию, но стоит понимать, что такая ситуация опасна, так как она может привести к взаимной блокировке потоков или аварийному завершению.

Ошибки в приоритетах

int sgetI1(unsigned char **bp) { int i; if (flen == FLEN_ERROR) return 0; i = **bp; if (i > 127) i -= 256; flen += 1; *bp++; return i; }
Предупреждение PVS-Studio : V532 Consider inspecting the statement of "*pointer++" pattern. Probably meant: "(*pointer)++". lwio.c 316

Ошибка связана с использованием инкремента. Для наглядности перепишем данное выражение, расставив скобки:
*(bp++);
То есть произойдёт сдвиг не содержимого по адресу bp, а самого указателя, что в данном контексте бессмысленно. Ниже по коду есть фрагменты вида *bp += N , из-за чего я и сделал вывод, что это ошибка.

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

Аналогичные предупреждения:

  • V532 Consider inspecting the statement of "*pointer++" pattern. Probably meant: "(*pointer)++". lwio.c 354
  • V532 Consider inspecting the statement of "*pointer++" pattern. Probably meant: "(*pointer)++". lwob.c 80
void CHitMemoryManager::load (IReader &packet) { .... if (!spawn_callback || !spawn_callback->m_object_callback) if(!g_dedicated_server) Level().client_spawn_manager().add(delayed_object.m_object_id,m_object->ID(),callback); #ifdef DEBUG else { if (spawn_callback && spawn_callback->m_object_callback) { VERIFY(spawn_callback->m_object_callback == callback); } } #endif // DEBUG }
Предупреждение PVS-Studio : V563 It is possible that this "else" branch must apply to the previous "if" statement. hit_memory_manager.cpp 368

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

Рекомендация проста - в более-менее сложных ветвлениях расставляйте фигурные скобки.
void HUD_SOUND_ITEM::PlaySound(HUD_SOUND_ITEM& hud_snd, const Fvector& position, const IGameObject* parent, bool b_hud_mode, bool looped, u8 index) { .... hud_snd.m_activeSnd->snd.set_volume(hud_snd.m_activeSnd->volume * b_hud_mode?psHUDSoundVolume:1.0f); }
Предупреждение PVS-Studio : V502 Perhaps the "?:" operator works in a different way than it was expected. The "?:" operator has a lower priority than the "*" operator. hudsound.cpp 108

У тернарного условного оператора приоритет ниже, чем у умножения, поэтому порядок операций будет следующим:
(hud_snd.m_activeSnd->volume * b_hud_mode)?psHUDSoundVolume:1.0f
Очевидно, что правильный код должен выглядеть так:
hud_snd.m_activeSnd->volume * (b_hud_mode?psHUDSoundVolume:1.0f)
Выражения, содержащие тернарный оператор, несколько if-else ветвей или операции И/ИЛИ, - это те случаи, когда лучше поставить лишние скобки.

Аналогичные предупреждения:

  • V502 Perhaps the "?:" operator works in a different way than it was expected. The "?:" operator has a lower priority than the "+" operator. uihudstateswnd.cpp 487
  • V502 Perhaps the "?:" operator works in a different way than it was expected. The "?:" operator has a lower priority than the "+" operator. uicellcustomitems.cpp 106

Лишние сравнения

void CDestroyablePhysicsObject::OnChangeVisual() { if (m_pPhysicsShell){ if(m_pPhysicsShell)m_pPhysicsShell->Deactivate(); .... } .... }
Предупреждение PVS-Studio : V571 Recurring check. The "if (m_pPhysicsShell)" condition was already verified in line 32. destroyablephysicsobject.cpp 33

В данном примере дважды проверяется m_pPhysicsShell . Скорее всего, вторая проверка лишняя.
void CSE_ALifeItemPDA::STATE_Read(NET_Packet &tNetPacket, u16 size) { .... if (m_wVersion > 89) if ((m_wVersion > 89)&&(m_wVersion < 98)) { .... }else{ .... } }
Предупреждение PVS-Studio : V571 Recurring check. The "m_wVersion > 89" condition was already verified in line 987. xrserver_objects_alife_items.cpp 989

Очень странный код. То ли здесь забыли выражение после if (m_wVersion > 89) , то ли целую серию else-if . Данный метод требует более подробного рассмотрения разработчиком проекта.
void ELogCallback(void *context, LPCSTR txt) { .... bool bDlg = ("#"==txt)||((0!=txt)&&("#"==txt)); if (bDlg){ int mt = ("!"==txt)||((0!=txt)&&("!"==txt))?1:0; .... } }
Предупреждения PVS-Studio :

  • V590 Consider inspecting the "(0 != txt) && ("#" == txt)" expression. The expression is excessive or contains a misprint. elog.cpp 29
  • V590 Consider inspecting the "(0 != txt) && ("!" == txt)" expression. The expression is excessive or contains a misprint. elog.cpp 31
В выражениях инициализации переменных bDlg и mt проверка (0 != txt) является избыточной. Если её опустить, выражения станут читаться значительно легче:
bool bDlg = ("#"==txt)||("#"==txt); int mt = ("!"==txt)||("!"==txt)?1:0;

Ошибки в типах данных


Float CRenderTarget::im_noise_time; CRenderTarget::CRenderTarget() { .... param_blur = 0.f; param_gray = 0.f; param_noise = 0.f; param_duality_h = 0.f; param_duality_v = 0.f; param_noise_fps = 25.f; param_noise_scale = 1.f; im_noise_time = 1/100; im_noise_shift_w = 0; im_noise_shift_h = 0; .... }
Предупреждение PVS-Studio : V636 The "1 / 100" expression was implicitly cast from "int" type to "float" type. Consider utilizing an explicit type cast to avoid the loss of a fractional part. An example: double A = (double)(X) / Y;. gl_rendertarget.cpp 245

Значение выражения 1/100 равно 0, так как выполняется операция целочисленного деления. Чтобы получить значение 0.01f, нужно использовать вещественный литерал, переписав выражение: 1/100.0f. Хотя возможно, что данное поведение было предусмотрено автором, и ошибки здесь нет.
CSpaceRestriction::merge(....) const { .... LPSTR S = xr_alloc(acc_length); for (; I != E; ++I) temp = strconcat(sizeof(S),S,*temp,",",*(*I)->name()); .... }
Предупреждение PVS-Studio : V579 The strconcat function receives the pointer and its size as arguments. It is possibly a mistake. Inspect the first argument. space_restriction.cpp 201

Функция strconcat , в качестве первого параметра принимает длину буфера. Буфер S объявлен, как LPSTR , то есть как указатель на строку. sizeof(S) будет равен размеру указателя в байтах, то есть sizeof(char *) , а не количеству символов в строке. Для вычисления длины следует использовать strlen(S) .
class XRCDB_API MODEL { .... u32 status; // 0=ready, 1=init, 2=building .... } void MODEL::build (Fvector* V, int Vcnt, TRI* T, int Tcnt, build_callback* bc, void* bcp) { .... BTHREAD_params P = { this, V, Vcnt, T, Tcnt, bc, bcp }; thread_spawn(build_thread,"CDB-construction",0,&P); while (S_INIT == status) Sleep(5); .... }
Предупреждение PVS-Studio : V712 Be advised that compiler may delete this cycle or make it infinity. Use volatile variable(s) or synchronization primitives to avoid this. xrcdb.cpp 100

Компилятор может убрать проверку S_INIT == status в качестве оптимизации, так как переменная status не модифицируется в цикле. Для того, чтобы избежать подобного поведения, нужно использовать volatile переменные или типы синхронизации данных между потоками.

Аналогичные предупреждения:

  • V712 Be advised that compiler may delete this cycle or make it infinity. Use volatile variable(s) or synchronization primitives to avoid this. levelcompilerloggerwindow.cpp 23
  • V712 Be advised that compiler may delete this cycle or make it infinity. Use volatile variable(s) or synchronization primitives to avoid this. levelcompilerloggerwindow.cpp 232
void CAI_Rat::UpdateCL() { .... if (!Useful()) { inherited::UpdateCL (); Exec_Look (Device.fTimeDelta); CMonsterSquad *squad = monster_squad().get_squad(this); if (squad && ((squad->GetLeader() != this && !squad->GetLeader()->g_Alive()) || squad->get_index(this) == u32(-1))) squad->SetLeader(this); .... } .... }
Предупреждение PVS-Studio : V547 Expression "squad->get_index(this) == u32(- 1)" is always false. The value range of unsigned char type: . ai_rat.cpp 480

Для того, чтобы понять, почему это выражение всегда ложно, вычислим значения отдельных операндов. u32(-1) равен 0xFFFFFFFF или 4294967295. Тип, возвращаемый методом squad->get_index(....) , - u8, следовательно его максимальное значение - 0xFF или 255, что строго меньше, чем u32(-1). Соответственно, значением такого сравнения всегда будет false . Данный код легко исправить, поменяв тип данных на u8:
squad->get_index(this) == u8(-1)
Та же диагностика срабатывает и для избыточных сравнений беззнаковых переменных:
namespace ALife { typedef u64 _TIME_ID; } ALife::_TIME_ID CScriptActionCondition::m_tLifeTime; IC bool CScriptEntityAction::CheckIfTimeOver() { return((m_tActionCondition.m_tLifeTime >= 0) && ((m_tActionCondition.m_tStartTime + m_tActionCondition.m_tLifeTime) < Device.dwTimeGlobal)); }
Предупреждение PVS-Studio : V547 Expression "m_tActionCondition.m_tLifeTime >= 0" is always true. Unsigned type value is always >= 0. script_entity_action_inline.h 115

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

Аналогичное предупреждение:

V547 Expression "m_tActionCondition.m_tLifeTime < 0" is always false. Unsigned type value is never < 0. script_entity_action_inline.h 143
ObjectFactory::ServerObjectBaseClass * CObjectItemScript::server_object (LPCSTR section) const { ObjectFactory::ServerObjectBaseClass *object = nullptr; try { object = m_server_creator(section); } catch(std::exception e) { Msg("Exception [%s] raised while creating server object from " "section [%s]", e.what(),section); return (0); } .... }
Предупреждение PVS-Studio : V746 Type slicing. An exception should be caught by reference rather than by value. object_item_script.cpp 39

Функция std::exception::what() является виртуальной и может быть переопределена в наследуемых классах. В данном примере исключение ловится по значению, следовательно, экземпляр класса будет скопирован и вся информация о полиморфном типе будет потеряна. Обращаться к what() в таком случае бессмысленно. Исключение стоит перехватывать по ссылке:
catch(const std::exception& e) {

Разное

void compute_cover_value (....) { .... float value ; .... if (value < .999f) { value = value; } .... }
Предупреждение PVS-Studio : V570 The "value" variable is assigned to itself. compiler_cover.cpp 260

Переменная value присваивается сама себе. Зачем это делать - непонятно. Возможно, ей должно было быть присвоено другое значение.
void CActor::g_SetSprintAnimation(u32 mstate_rl, MotionID &head, MotionID &torso, MotionID &legs) { SActorSprintState& sprint = m_anims->m_sprint; bool jump = (mstate_rl&mcFall) || (mstate_rl&mcLanding) || (mstate_rl&mcLanding) || (mstate_rl&mcLanding2) || (mstate_rl&mcJump); .... }
Предупреждение PVS-Studio : V501 There are identical sub-expressions "(mstate_rl & mcLanding)" to the left and to the right of the "||" operator. actoranimation.cpp 290

Вероятнее всего здесь просто лишняя проверка mstate_rl & mcLanding , но часто подобные предупреждения сигнализируют об ошибке в логике и нерассмотренных значениях enum.

Аналогичные предупреждения:

  • V501 There are identical sub-expressions "HudItemData()" to the left and to the right of the "&&" operator. huditem.cpp 338
  • V501 There are identical sub-expressions "list_idx == e_outfit" to the left and to the right of the "||" operator. uimptradewnd_misc.cpp 392
  • V501 There are identical sub-expressions "(D3DFMT_UNKNOWN == fTarget)" to the left and to the right of the "||" operator. hw.cpp 312
RELATION_REGISTRY::RELATION_MAP_SPOTS::RELATION_MAP_SPOTS() { .... spot_names = "enemy_location"; spot_names = "enemy_location"; .... }
Предупреждение PVS-Studio : V519 The variable is assigned values twice successively. Perhaps this is a mistake. Check lines: 57, 58. relation_registry.cpp 58

Анализатор обнаружил, что одной переменной присваиваются подряд два значения. В данном случае похоже, что это просто мёртвый код и его стоит удалить.
void safe_verify(....) { .... printf("FATAL ERROR (%s): failed to verify data\n"); .... }
Предупреждение PVS-Studio : V576 Incorrect format. A different number of actual arguments is expected while calling "printf" function. Expected: 2. Present: 1. entry_point.cpp 41

В функцию printf передаётся недостаточное количество аргументов: формат "%s" указывает на то, что должен быть передан указатель на строку. Такая ситуация может привести к ошибке доступа к памяти и экстренному завершению программы.

  • pvs-studio
  • static code analysis
  • C++
  • stalker
  • Добавить метки

    X-Ray Engine – движок, который использовался в основных играх серии «СТАЛКЕР» и дополнений к ним. Был создан разработчиком игр GSC Game World. Включает в себя исходный код и инструменты для разработки (SDK).

    Движок X-Ray Engine поддерживает DirectX с версии 9.0 по 11. Также в нем реализована технология отложенного освещения, благодаря которой реалистично отрисовывается эффект освещения. Также поддерживается смена времени суток, изменение погоды и мягкие тени. Физика в основана на другом движке Open Dynamics Engine. Он обеспечивает реалистичную механику столкновений и динамику движения твердых тел.

    Помимо исходного кода, X-Ray Engine содержит инструментарий для разработки программного обеспечения (SDK). Он в первую очередь пригодится мододелам, которые хотели бы создать и добавить в игру собственные модификации.

    Особенности движка

    Применялся при создании игр серии «СТАЛКЕР».
    Поддерживает DirectX версий с 9 по 11.
    Поддерживает отложенное освещение, погодные явления, реалистичную механику столкновений.
    Содержит инструменты для разработки собственных модификаций.

    X-Ray Engine и инструментарий к нему свободно распространяется, поэтому движок можно скачать бесплатно.

    В далеком 2006 году увидела свет лучшая игра всех времён и народов – STALKER.

    Эта игра разрабатывалась на протяжении шести лет, и многие геймеры уже не верили в её выход. Но в 2006 году – всё же свершилось. Сталкер превзошел все ожидания, и многие фанаты по нескольку раз на одном дыхании проходили «Тень Чернобыля».

    В 2008 году вышла в свет очередная часть этой увлекательной игры – «Чистое небо» , а уже через год появилась – «Зов Припяти».

    Именно в этой части Сталкера у игроков наиболее часто стала появляться одна проблема – «Ошибка Xray Engine 1.6», и в данном обзоре мы постараемся рассказать пользователям, как бороться с этой проблемой.

    «Жук счастья»

    Именно так прозвали эту ошибку геймеры , так как при появлении выскакивала табличка с описанием ошибки, где слева был нарисован зелёненький жучок. Когда появлялась ошибка X-ray Engine 1.6 – игра произвольно закрывалась с выходом на рабочий стол.

    В Интернете мало было инфы о решении проблемы, да и от самих производителей не исходило практически никакой информации по данной ошибке, но одержимые геймеры не сдавались – искали решение проблемы везде, где только можно.

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

    Поиск и устранение причин

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

    Уже в «Тень Чернобыля» стала изредка появляться ошибка X-ray Engine 1.6, но она была недостаточно назойлива , и более-менее можно было проходить игру.

    Когда разработчики «обкатали» новый патч 1.5.04, то проблему с «жуком» практически полностью удалось решить. Но всё это при условии, если вы скачиваете лицензионную версию игры, которая в своем арсенале имеет все необходимые патчи.

    Еще одной самой распространенной причиной возникновения ошибки X-ray Engine 1.6, является использование пиратских «кряков» . Так как Stalker на тот момент был защищен всем известной антипиратской – StarForce, то применение всякого рода пиратского софта вело к появлению ошибки с «жуком».

    В этом случае существует только одно решение – приобрести Stalker, скажем, в Стиме, и без проблем играть не боясь, что увлекательный игровой процесс прервет надоедливая – X-ray Engine 1.6.

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

    Без сомнений, что моды делают Stalker гораздо колоритней, но именно они зачастую являются причиной появления ошибки X-ray Engine 1.6.

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

    Есть еще причина возникновения ошибки X-ray Engine 1.6 – это использование всякого рода «читов» для быстрого прохождения. Если вы будете усердствовать с употреблением читерских кодов – бесконечный боекомплект, какое-нибудь мощное оружие и так далее, то в данном случае вы приобретаете большую вероятность того, что в процессе игры столкнетесь с ошибкой X-ray Engine 1.6.

    Перегруженность игры «читами» ведет к потере стабильности самим движком X-ray, а появляющиеся фризы и лаги провоцируют появление «жука несчастья». Геймер должен отдавать себе отчет, что допустимо в игре Stalker, а что уже чересчур – в плане «читов». Чем меньше вы используете в игре «костылей», тем стабильнее и без ошибок будет у вас работать Stalker.

    Также наблюдались случаи появления ошибки, когда настройки монитора устанавливались – индивидуально.

    Для того, чтобы Stalker работал у вас безошибочно, настройки монитора должны быть «рекомендуемыми», и это в большинстве случаев избавят вас от назойливого «жука».

    В заключение хотелось бы обратить внимание на ещё один важный момент, из-за которого возникает ошибка X-ray Engine 1.6. Этот трабл может появиться тогда, когда pagefile.sys имеет недостаточный размер для стабильной работы системы – в целом.

    В случае со Сталкером, «подкачка» должна превышать минимум в два раза размер вашей ОЗУ, и только тогда вы добьетесь стабильности в игре, и «X-ray Engine 1.6» покинет вас навсегда. Как настроить размер файла подкачки мы здесь рассказывать не будем, так как это давно уже в гугле описано в мельчайших подробностях.

    Вывод

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

    Да, не обошлось и без проблем, и основные методы решения этих проблем мы сегодня с вами изучили. Приятной игры!

    Поделиться: