L'industrie du jeu ne reste pas immobile et se développe de plus en plus vite chaque jour. Parallèlement à la croissance de l'industrie, la complexité du développement augmente également: il y a plus de code et plus de bogues. Par conséquent, les projets de jeux modernes nécessitent une attention particulière à la qualité du code. Aujourd'hui, nous allons parler de l'un des moyens d'améliorer votre code - l'analyse statique, ainsi que de la manière dont PVS-Studio aide dans la pratique au développement de grands projets de jeux (et pas seulement).
« La chose la plus importante que j'ai faite en tant que programmeur ces dernières années est de poursuivre de manière agressive l'analyse statique du code. Encore plus précieux que les centaines de bogues sérieux que j'ai évités, c'est le changement de mentalité concernant la façon dont je vois la fiabilité et le code des logiciels. qualité. "- John Carmack
Nous travaillons avec les principaux développeurs de jeux depuis de nombreuses années et pendant ce temps, nous avons réussi à faire beaucoup de choses intéressantes et utiles pour l'industrie du jeu. Cela n'est pas surprenant compte tenu de la liste de nos clients de l'industrie du jeu vidéo. Nous fournissons un support actif à nos clients: nous les aidons à intégrer PVS-Studio dans leur propre processus de développement, à corriger les erreurs trouvées par l'analyseur et même à créer des fonctionnalités spéciales sur commande.
De plus, nous faisons beaucoup de développement indépendant de l'analyseur dans le sens GameDev, et nous popularisons également PVS-Studio en informant les gens des bogues intéressants qu'il a trouvés dans divers jeux vidéo.
Naturellement, non sans histoires intéressantes. Plusieurs de ces histoires seront discutées dans cet article.
PVS-Studio et Unity
L'une des façons dont nous faisons la promotion de notre produit consiste à rédiger des articles sur la révision de projets open source. Tout le monde profite de ces articles: le lecteur peut regarder des erreurs intéressantes dans un projet familier et apprendre quelque chose de nouveau par lui-même, nous avons l'opportunité de montrer le travail de PVS-Studio en code réel, et les développeurs de projets peuvent en apprendre davantage sur les erreurs et les corriger à l'avance.
Notre première connaissance sérieuse avec Unity a commencé en 2016, lorsque les développeurs de ce moteur de jeu ont publié le code source de plusieurs composants, bibliothèques et démos dans leur référentiel officiel. Naturellement, nous ne pouvions pas passer par un cas aussi "savoureux" et voulions écrire un article sur la vérification du code présenté.
Ensuite, nous avons constaté que le code Unity3D (à l'époque, le moteur s'appelait ainsi) est de très haute qualité, cependant, nous avons réussi à y trouver beaucoup d'erreurs graves pour écrire un article .
Deux ans plus tard, un autre événement s'est produit - cette fois, les développeurs Unity ont publié le code du moteur lui-même et l'éditeur pour ouvrir l'accès. Et tout comme la fois précédente, nous n'avons pas pu passer et vérifier le code source du moteur. Et pour cause: nous avons également trouvé une poignée d' erreurs intéressantes .
Cependant, rédiger des articles est loin d'être tout. Nous continuons à travailler sur PVS-Studio et GameDev est l'un des domaines de développement les plus importants pour nous. Par conséquent, nous voulons que les développeurs de jeux Unity puissent obtenir la meilleure analyse possible de leurs projets.
L'une des étapes pour améliorer la qualité de l'analyse des projets Unity pour nous était d'écrire des annotations pour les méthodes définies dans l'API Unity Scripting.
Les annotations de méthode sont un mécanisme spécial utilisé dans PVS-Studio. Il vous permet de fournir à l'analyseur toutes les informations dont il a besoin sur une méthode particulière. Il est écrit dans un code spécial par les développeurs de l'analyseur eux-mêmes (c'est-à-dire par nous).
Ces informations peuvent être d'une nature complètement différente. Par exemple: comment une méthode peut affecter les paramètres qui lui sont passés, si elle peut allouer de la mémoire et si elle renvoie une valeur qui doit être traitée. Ainsi, l'annotation permet à l'analyseur de mieux comprendre la logique des méthodes, lui permettant ainsi de détecter des erreurs nouvelles et plus complexes.
Nous avons déjà écrit une grande variété d'annotations différentes (par exemple, pour les méthodes de l'espace de noms System), et nous étions heureux de les compléter avec des annotations de méthode de l'API Unity Scripting.
Nous avons commencé à ajouter à la liste des annotations avec une évaluation. Combien de méthodes existe-t-il? Lesquels doivent être annotés en premier? Il y avait beaucoup de méthodes au total, et nous avons décidé de commencer par annoter les méthodes les plus fréquemment utilisées.
La recherche de méthodes populaires s'est déroulée comme suit: tout d'abord, nous avons collecté un pool de projets de GitHub qui utilisent les capacités de Unity, puis, à l'aide d'un utilitaire auto-écrit (basé sur Roslyn), nous avons compté les appels des méthodes qui nous intéressent. En conséquence, nous avons obtenu une liste de classes dont les méthodes sont le plus souvent utilisées:
- UnityEngine.Vector3
- UnityEngine.Mathf
- UnityEngine.Debug
- UnityEngine.GameObject
- UnityEngine.Material
- UnityEditor.EditorGUILayout
- UnityEngine.Component
- UnityEngine.Object
- UnityEngine.GUILayout
- UnityEngine.Quaternion
- ...
Ensuite, il reste à annoter les méthodes de ces classes. Nous avons créé un projet de test et fouillé dans la documentation pour obtenir le plus d'informations possible sur ces méthodes. Par exemple, nous avons essayé de passer null comme divers arguments pour voir comment le programme se comporte.
Au cours de ces vérifications, des informations non documentées intéressantes ont été périodiquement découvertes - et nous avons même trouvé quelques bogues intéressants dans le moteur. Donc, lors de l'exécution de code comme celui-ci:
MeshRenderer renderer = cube.GetComponent<MeshRenderer>();
Material m = renderer.material;
List<int> outNames = null;
m.GetTexturePropertyNameIDs(outNames);
l'éditeur Unity lui-même plante directement (au moins dans la version 2019.3.10f1). Il est peu probable, bien sûr, que quelqu'un écrive un tel code, mais le fait même que l'éditeur Unity puisse être «renversé» en exécutant un tel script est intéressant.
Ainsi, les annotations sont écrites. Après avoir commencé l'analyse, nous avons immédiatement découvert de nouveaux déclencheurs. Par exemple, l'analyseur a détecté un appel étrange à la méthode GetComponent :
void OnEnable()
{
GameObject uiManager = GameObject.Find("UIRoot");
if (uiManager)
{
uiManager.GetComponent<UIManager>();
}
}
Avertissement de l'analyseur: V3010 La valeur de retour de la fonction «GetComponent» doit être utilisée. - SUPPLÉMENTAIRE DANS UIEditorWindow.cs ACTUEL 22
La méthode GetComponent même par son nom implique le retour d'une certaine valeur. Il est logique de supposer que cette valeur même doit être utilisée d'une manière ou d'une autre. Désormais (grâce à la nouvelle annotation) l'analyseur sait qu'un tel appel "orphelin" à cette méthode peut indiquer une erreur logique et vous en avertit.
C'est loin d'être le seul déclencheur qui est apparu dans notre ensemble de projets de test après l'ajout de nouvelles annotations - je ne donnerai pas le reste pour ne pas rendre cet article trop volumineux. L'essentiel est que maintenant le développement de projets Unity à l'aide de PVS-Studio vous permet d'écrire du code beaucoup plus sûr et plus propre sans bugs.
Si vous souhaitez en savoir plus sur notre travail avec les annotations pour les méthodes Unity, vous pouvez le faire dans notre article: Comment l'analyseur PVS-Studio a commencé à trouver encore plus d'erreurs dans les projets Unity .
Unreal Engine 4
Lorsque, en 2014, les développeurs d'Unreal Engine 4 ont publié le code source du moteur au public, nous ne pouvions tout simplement pas ignorer ce projet et avons également écrit un article à ce sujet . Les développeurs de moteurs ont aimé l'article et ont corrigé les bogues que nous avons trouvés. Mais cela ne nous suffisait pas et nous avons décidé d'essayer de vendre la licence de notre analyseur à Epic Games.
Epic Games souhaitait améliorer son moteur en utilisant PVS-Studio, nous avons donc convenu d'un accord: nous corrigeons le code Unreal Engine nous-mêmes afin que l'analyseur n'émette aucun avertissement à ce sujet, et les gars d'Epic Games achètent notre licence et en plus récompensez-nous pour le travail que nous faisons.
Pourquoi avez-vous eu besoin de corriger tous les avertissements? Le fait est que le bénéfice maximal de l'analyse statique peut être obtenu en corrigeant les erreurs dès qu'elles apparaissent . Et lorsque vous vérifiez votre projet pour la première fois, en règle générale, vous recevez plusieurs centaines (et parfois des milliers) d'avertissements. Parmi tous ces avertissements de l'analyseur, les avertissements émis pour du code fraîchement écrit peuvent facilement être perdus.
À première vue, ce problème peut être résolu assez facilement: il vous suffit de vous asseoir et de contourner complètement l'ensemble du rapport, en corrigeant progressivement les erreurs. Cependant, cette méthode, bien que plus intuitive, peut prendre du temps. La méthode d'utilisation des fichiers de suppression est beaucoup plus pratique et plus rapide.
Les fichiers de suppression sont une fonction spéciale de PVS-Studio, qui vous permet de "masquer" les déclencheurs de l'analyseur dans un fichier spécial. Dans ce cas, les avertissements masqués n'apparaîtront pas dans les journaux suivants: ils peuvent être consultés séparément.
Après avoir reçu un grand nombre de déclencheurs après la première vérification, vous pouvez ajouter tous les déclencheurs détectés au fichier de suppression en quelques clics, puis, lors de la prochaine vérification par l'analyseur, vous recevrez un journal propre sans un seul déclencheur.
Maintenant que les anciens avertissements ne sont plus enregistrés, vous pouvez facilement repérer un nouvel avertissement dès qu'il apparaît. Nous avons écrit le code -> vérifié avec l'analyseur -> vu un nouvel avertissement -> corrigé l'erreur. C'est ainsi que vous tirez le meilleur parti de votre analyseur.
Dans le même temps, n'oubliez pas les alarmes qui se trouvent dans le fichier de suppression: elles sont les mêmes qu'auparavant, elles peuvent contenir des avertissements sur des erreurs et des vulnérabilités graves. Par conséquent, il vaut la peine de revenir périodiquement sur ces avertissements et de réduire leur nombre.
Ce scénario est pratique, bien sûr, mais les développeurs d'Epic Games voulaient que leur code soit corrigé immédiatement, et ils nous l'ont confié.
Et nous devons travailler. Après vérification du code du projet, nous avons trouvé 1821 un niveau d'avertissement Level_1 et Level_2. L'analyse d'un tel volume d'avertissements nécessite un travail sérieux, et pour faciliter l'ensemble de ce processus, nous avons mis en place une analyse continue du code sur notre serveur CI.
Cela ressemblait à ceci: chaque nuit, la version actuelle d'Unreal Engine 4 était compilée sur notre serveur et l'analyse était automatiquement lancée immédiatement après la construction. Ainsi, lorsque nos gars venaient travailler le matin, ils avaient toujours un nouveau rapport d'analyse sous la main, leur permettant de suivre les progrès dans la correction des avertissements. De plus, un tel système permettait de vérifier la stabilité de la construction à tout moment en l'exécutant manuellement sur le serveur.
L'ensemble du processus nous a pris 17 jours ouvrables. Le calendrier de correction des avertissements est le suivant:
En fait, ce tableau ne reflète pas pleinement notre travail. Après avoir corrigé tous les avertissements, nous avons attendu encore deux jours pour qu'ils acceptent nos dernières demandes d'extraction. Pendant tout ce temps, nous avons continué à vérifier automatiquement la dernière version d'Unreal Engine, qui, à son tour, a continué à être réapprovisionnée avec un nouveau code. Et qu'en penses-tu? Pendant ces deux jours, PVS-Studio a trouvé quatre autres erreurs dans le code! L'un d'eux était particulièrement grave et pouvait conduire à un comportement indéfini.
Bien sûr, nous avons également corrigé ces erreurs. Désormais, les développeurs d'Unreal Engine n'ont plus qu'une chose: configurer leur analyse automatique de la même manière que nous. À partir de ce moment, ils ont commencé à voir des avertissements chaque jour, qui étaient émis pour le code nouvellement écrit. Cela leur a permis de corriger les bogues dans le code même au moment où ils sont apparus - aux tout premiers stades de développement .
Vous pouvez en savoir plus sur la façon dont nous avons travaillé sur le code Unreal Engine sur le blog officiel Unreal Engine ou sur notre site Web .
Analyse de divers jeux
Ai-je mentionné que nous vérifions divers projets open source et écrivons des articles à leur sujet? Nous avons donc tout un tas d'articles similaires sur les projets de jeux! Nous avons écrit sur des jeux comme VVVVVV , Space Engineers , Command & Conquer , osu! et même (article très ancien) Doom 3 . Nous avons également compilé le top 10 des bugs les plus intéressants de l'industrie du jeu vidéo.
Nous avons également vérifié peut-être la plupart des moteurs open source bien connus. En plus de Unity et Unreal Engine 4, des projets tels que Godot , Bullet , Amazon Lumberyard , Cry Engine V sont tombés sous nos yeuxet plein d'autres.
La meilleure partie de tout cela est que de nombreux bogues que nous avons décrits ont été corrigés par les développeurs du projet eux-mêmes. Il est bon de sentir que l'outil que vous développez apporte des avantages réels, visibles et tangibles au monde.
Vous pouvez consulter une liste de tous nos articles, d'une manière ou d'une autre liés au développement de jeux vidéo sur une page spéciale de notre blog.
Conclusion
Ceci conclut mon court article. Je vous souhaite un code propre et fonctionnant correctement, sans bugs ni erreurs!
Intéressé par le sujet de l'analyse statique? Voulez-vous vérifier votre projet pour les erreurs? Essayez PVS-Studio .
Si vous souhaitez partager cet article avec un public anglophone, veuillez utiliser le lien de traduction: George Gribkov. Comment l'analyse de code statique aide dans l'industrie GameDev .