Hoe analyse van statische code helpt in de GameDev-industrie

( 4 december 2020)

De game-industrie is constant in ontwikkeling en ontwikkelt zich sneller dan een snel vliegende kogel. Samen met de groei van de industrie neemt ook de complexiteit van de ontwikkeling toe: de codebasis wordt groter en het aantal bugs groeit ook. Daarom moeten moderne gameprojecten speciale aandacht besteden aan de codekwaliteit. Vandaag behandelen we een van de manieren om uw code fatsoenlijker te maken, namelijk statische analyse, en ook hoe PVS-Studio in de praktijk helpt bij de ontwikkeling van gameprojecten van verschillende groottes.

“Het belangrijkste dat ik de afgelopen jaren als programmeur heb gedaan, is om agressief statische code-analyse na te streven. Nog waardevoller dan de honderden ernstige bugs die ik ermee heb voorkomen, is de verandering in de manier waarop ik naar de betrouwbaarheid van software en de kwaliteit van de code kijk. “- John Carmack

We werken al vele jaren samen met grote game-ontwikkelaars en gedurende deze tijd zijn we erin geslaagd veel interessante en nuttige dingen te doen voor de game-industrie. Het is niet echt een verrassing, gezien de lijst van onze klanten uit de game-industrie. We ondersteunen onze klanten actief: om PVS-Studio te integreren in hun eigen ontwikkelingsproces, fouten te herstellen die door de analyzer zijn gevonden, en we maken zelfs speciale aangepaste functies.

Daarnaast doen we veel onafhankelijke ontwikkeling van de analyzer in de GameDev-richting, en promoot ook PVS-Studio door mensen te vertellen over interessante fouten die het in verschillende videogames heeft gevonden.

Natuurlijk hebben we een aantal interessante verhalen te vertellen. Dit artikel behandelt verschillende van dergelijke gevallen.

PVS-Studio en Unity

Een van de manieren waarop we ons product promoten, is door artikelen te schrijven over het controleren van openstaande projecten. Iedereen heeft baat bij deze artikelen: een lezer krijgt de kans om enkele ongebruikelijke fouten in een bekend project te bekijken en iets nieuws te leren. Wat betreft het PVS-Studio-team, we krijgen de kans om het werk dat aan echte code is gedaan te laten zien, zodat projectontwikkelaars over fouten kunnen leren en deze van tevoren kunnen oplossen.

Onze eerste grote kennismaking met Unity vond plaats in 2016, toen de ontwikkelaars van deze game-engine de broncode van verschillende componenten, bibliotheken en demos openden in hun officiële repository. Geen wonder, we konden niet voorbijgaan aan zon aanlokkelijk geval en wilden een artikel schrijven over het controleren van de geplaatste code.

Toen kwamen we erachter dat de Unity3D-code (op dat moment werd de engine zo genoemd) was van zeer hoge kwaliteit. Maar toch hebben we er behoorlijk wat ernstige fouten in kunnen vinden. Er waren er genoeg om een ​​ artikel te schrijven.

Twee jaar later gebeurde er iets anders – Unity-ontwikkelaars openden de code van de engine en de redacteur zelf. En net als de vorige keer konden we daar geen acht op slaan en controleerden we de broncode van de motor. En het was niet voor niets – we vonden ook een stelletje boeiende tekortkomingen.

Tegelijkertijd gaan onze bedoelingen veel verder dan alleen schrijven Lidwoord. We blijven werken aan PVS-Studio en GameDev is een van de belangrijkste gebieden voor onze ontwikkeling. Daarom willen we dat game-ontwikkelaars van Unity de best mogelijke analyse van hun projecten kunnen krijgen.

Een van de stappen om de kwaliteit van de analyse van Unity-projecten te verbeteren, was het schrijven van annotaties voor methoden die zijn gedefinieerd in de Unity Scripting API .

Annotatie van methoden is een speciaal mechanisme dat wordt gebruikt in PVS-Studio. Het stelt een gebruiker in staat om de analysator alle nodige informatie over een bepaalde methode te geven. Het is in speciale code geschreven door de ontwikkelaars van de analyzer zelf (d.w.z. door ons).

Deze informatie kan van totaal verschillende soorten zijn. Bijvoorbeeld: hoe de methode de parameters die eraan worden doorgegeven kan beïnvloeden, of het geheugen kan toewijzen en of het een waarde retourneert die moet worden afgehandeld. Annotatie stelt de analysator dus in staat de logica van methoden beter te begrijpen, waardoor hij nieuwe en complexere fouten kan detecteren.

We hebben al een groot aantal verschillende annotaties geschreven (bijvoorbeeld voor methoden uit het systeem namespace), en we waren blij om methode-annotaties van de Unity Scripting API eraan toe te voegen.

We begonnen de lijst met annotaties uit te breiden met een evaluatie. Hoeveel methoden zijn er in totaal? Welke moeten eerst worden geannoteerd? Er waren in totaal veel methoden, dus we besloten om te beginnen met het annoteren van de meest gebruikte methoden.

Dit is hoe we op zoek waren naar populaire methoden: eerst verzamelden we een pool van projecten van GitHub die Unity-functies gebruiken, en vervolgens gebruikten we een zelfgeschreven hulpprogramma (gebaseerd op Roslyn) om aanroepen naar de methoden waarin we waren geïnteresseerd. Als resultaat kregen we een lijst met klassen waarvan de methoden het meest werden gebruikt:

  • UnityEngine.Vector3
  • UnityEngine.Mathf
  • UnityEngine.Debug
  • UnityEngine.GameObject
  • UnityEngine.Material
  • UnityEditor.EditorGUILayout
  • UnityEngine.Component
  • UnityEngine.Object
  • UnityEngine.GUILayout
  • UnityEngine.Quaternion

Vervolgens bleef het om de methoden van deze klassen te annoteren. We hebben een testproject gemaakt en in de documentatie gedoken om zoveel mogelijk informatie over die methoden te krijgen. We hebben bijvoorbeeld geprobeerd null door te geven als verschillende argumenten om te zien hoe het programma zich zou gedragen.

Tijdens dergelijke controles ontdekten we van tijd tot tijd wat interessante ongedocumenteerde informatie. We hebben zelfs een paar opmerkelijke bugs in de motor gevonden. Als we bijvoorbeeld de volgende code gebruiken:

MeshRenderer renderer = cube.GetComponent();
Material m = renderer.material;
List<int> outNames = null;
m.GetTexturePropertyNameIDs(outNames);

crasht de Unity-editor zelf (tenminste in versie 2019.3.10f1). Het is natuurlijk onwaarschijnlijk dat iemand dergelijke code zal schrijven. Toch is het merkwaardig dat de Unity-editor kan worden gecrasht door een dergelijk script uit te voeren.

Dus we hadden de annotaties geschreven. Na het uitvoeren van de analyse vonden we direct nieuwe triggers. De analysator heeft bijvoorbeeld een vreemde aanroep naar de GetComponent -methode gedetecteerd:

void OnEnable()
{
GameObject uiManager = GameObject.Find("UIRoot"); if (uiManager)
{
uiManager.GetComponent();
}
}

Analyzer-waarschuwing: V3010 De retourwaarde van de functie GetComponent is vereist om te worden gebruikt. – AANVULLEND IN HUIDIGE UIEditorWindow.cs 22

De GetComponent -methode impliceert het teruggeven van een specifieke waarde, zelfs naar zijn naam. Het is logisch om aan te nemen dat deze waarde op de een of andere manier moet worden gebruikt. Dankzij de nieuwe annotatie weet de analysator nu dat een dergelijke “onbeheerde” aanroep naar deze methode kan duiden op een logische fout en waarschuwt hij ervoor.

Dit is niet de enige waarschuwing die in de set van onze test projecten na het toevoegen van nieuwe annotaties. De rest zal ik niet noemen, om dit artikel niet te groot te maken. Het belangrijkste is dat je nu met de ontwikkeling van Unity-projecten met behulp van PVS-Studio veel veiligere en schonere code kunt schrijven zonder bugs.

Als je meer wilt lezen over ons werk met annotaties voor Unity-methoden, hier is het artikel: Hoe de PVS-Studio-analyzer nog meer fouten begon te vinden in Unity-projecten .

Unreal Engine 4

Wanneer, in 2014, de ontwikkelaars van Unreal Engine 4 opende de broncode van de engine, we konden gewoon niet voorbij dat project komen en schreven er ook een artikel over. De engine-ontwikkelaars vonden het artikel leuk en hebben de gevonden fouten opgelost. Maar dit was niet genoeg voor ons, en we besloten om te proberen de licentie voor onze analyzer aan Epic Games te verkopen.

Epic Games was geïnteresseerd in het verbeteren van zijn engine met PVS-Studio, dus kwamen we het volgende overeen : we repareren de Unreal Engine-code zelf zodat de analyzer geen waarschuwingen geeft, en jongens van Epic Games kopen onze licentie en belonen ons bovendien voor het geleverde werk.

Waarom moesten alle waarschuwingen worden gemaakt? Het feit is dat men het maximale voordeel kan halen uit statische analyse door fouten direct wanneer ze verschijnen te corrigeren. Wanneer u uw project voor de eerste keer controleert, krijgt u meestal honderden (en soms duizenden) waarschuwingen. Tussen al deze triggers van analyzers is het gemakkelijk om waarschuwingen voor nieuw geschreven code kwijt te raken.

Op het eerste gezicht kan dit probleem vrij eenvoudig worden opgelost: u hoeft alleen maar te gaan zitten en het hele rapport door te nemen. , waardoor fouten geleidelijk worden gecorrigeerd. Hoewel deze methode intuïtiever is, kan het even duren. Het is veel handiger en sneller om bestanden onderdrukken te gebruiken.

Bestanden onderdrukken is een speciale functie van PVS-Studio waarmee u zich kunt verbergen analyserwaarschuwingen in een speciaal bestand. Verborgen waarschuwingen verschijnen echter niet in volgende logboeken: u kunt ze afzonderlijk bekijken.

Nadat u na de eerste controle veel triggers heeft gehad, kunt u alle gedetecteerde waarschuwingen met een paar klikken aan het onderdrukkingsbestand toevoegen, en u krijgt een schoon logboek zonder een enkele invoer na de volgende controle.

Nu de oude waarschuwingen niet langer in het logboek zijn opgenomen, kunt u gemakkelijk een nieuwe waarschuwing onmiddellijk detecteren wanneer deze verschijnt. Hier is de volgorde van acties: schrijf de code -> controleer deze met de analysator -> zoek een nieuwe waarschuwing -> los de fout op. Op deze manier haalt u het meeste uit het gebruik van de analyser.

Vergeet tegelijkertijd de waarschuwingen in het onderdrukkingsbestand niet: ze kunnen nog steeds waarschuwingen bevatten over grote fouten en kwetsbaarheden, net als voorheen. Daarom moet men terugkomen op deze waarschuwingen en hun aantal regelmatig verminderen.

Geen twijfel mogelijk, dit scenario is handig, maar ontwikkelaars van Epic Games wilden dat hun code meteen werd gerepareerd, dus slaagden ze voor de taak voor ons.

En we gingen aan de slag. Na controle van de projectcode vonden we 1821 waarschuwingen van Level_1 en Level_2. Het ontleden van zon groot aantal waarschuwingen vereist serieus werk, en om dit hele proces te vergemakkelijken, hebben we continue code-analyse opgezet op onze CI-server.

Het zag er zo uit: elke avond op onze server, de huidige versie van Unreal Engine 4 werd gebouwd en onmiddellijk na de build werd de analyse automatisch gestart. Dus toen onze jongens s ochtends naar hun werk kwamen, hadden ze altijd een nieuw rapport van de analysator, waardoor ze de voortgang van het elimineren van waarschuwingen konden volgen. Bovendien konden we met dit systeem de stabiliteit van de build op elk moment controleren door het handmatig op de server uit te voeren.

Het hele proces kostte ons 17 werkdagen. Het schema voor het oplossen van fouten was als volgt:

In feite weerspiegelt dit schema ons werk niet volledig. Nadat we alle waarschuwingen hadden opgelost, wachtten we nog twee dagen totdat ze onze laatste pull-verzoeken accepteerden. Al die tijd werd de nieuwste versie van Unreal Engine automatisch gecontroleerd, die op zijn beurt weer werd bijgewerkt met nieuwe code. Dus, wat denk je dat er is gebeurd? Tijdens die twee dagen vond PVS-Studio nog vier fouten in de code! Een ervan was cruciaal en kon mogelijk leiden tot ongedefinieerd gedrag.

Natuurlijk hebben we ook die fouten verholpen. Op dat moment hadden ontwikkelaars van Unreal Engine nog maar één ding over: automatische analyse op hun eigen plek opzetten, net zoals we hebben gedaan. Vanaf dat moment begonnen ze elke dag waarschuwingen te zien die werden uitgegeven voor de code die ze zojuist hadden geschreven. Hierdoor konden ze fouten in de code corrigeren zodra ze verschenen – in de vroegste ontwikkelingsstadia .

U kunt meer lezen over hoe we aan de Unreal Engine-code werkten in de officiële Unreal Engine-blog of op onze website .

Analyse van verschillende spellen

Had ik al gezegd dat we verschillende openstaande projecten nakijken en er artikelen over schrijven? We hebben nu dus een heleboel vergelijkbare artikelen over gameprojecten! We schreven over games als VVVVVV , Space Engineers , Command & Conque r, osu! en zelfs (een heel vroeg artikel) Doom 3 . We hebben ook de top 10 van de meest interessante softwarefouten uit de videogame-industrie samengesteld.

Dus hebben we waarschijnlijk de meeste van de bekende open source-engines. Naast Unity en Unreal Engine 4, projecten zoals Godot , Bullet , Amazon Lumberyard , Cry Engine V en vele anderen zijn onder onze aandacht gekomen.

Het beste van dit alles is dat veel van de bugs die we beschreven hebben later door de projectontwikkelaars zelf zijn opgelost. Het is prettig om te voelen dat de tool die u aan het ontwikkelen bent echte, zichtbare en tastbare voordelen voor de wereld oplevert.

U kunt een lijst van al onze artikelen over de ontwikkeling van videogames op de een of andere manier bekijken op een speciale pagina van onze blog.

Conclusie

Op dit punt loopt mijn artikel ten einde. Ik wens je schone en correct werkende code zonder bugs en fouten!

Geïnteresseerd in het onderwerp statische analyse? Wilt u uw project op fouten controleren? Probeer PVS-Studio .

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *