Position actuelle: Accueil> Derniers articles> hash_final Comment éviter les fuites de mémoire lors du calcul du hachage?

hash_final Comment éviter les fuites de mémoire lors du calcul du hachage?

gitbox 2025-05-20

Dans PHP, Hash_Final () est une fonction liée au contexte de hachage, qui est utilisé pour finalement calculer la valeur de hachage après avoir appelé plusieurs fois hash_init () et hash_update () . Il est très important d'utiliser correctement Hash_Final () , sinon il peut entraîner des fuites de mémoire, en particulier dans les scripts qui s'exécutent pendant longtemps ou qui doivent traiter de grandes quantités de données.

Cet article expliquera pourquoi les fuites de mémoire se produisent et fourniront des exemples de code réels pour vous apprendre à utiliser Hash_Final () en toute sécurité.

1 ?? Revue de la fonction de la série de hachage

PHP fournit les fonctions suivantes liées au calcul du hachage:

  • hash_init (String $ algo) : initialise un contexte de hachage.

  • hash_update (Resource $ context, string $ data) : ajoutez des données au contexte.

  • hash_final (Resource $ context, bool $ raw_output = false) : obtenez le résultat du hachage final.

Exemple de code:

 <?php
$context = hash_init('sha256');
hash_update($context, 'Hello, world!');
$hash = hash_final($context);
echo $hash;
?>

Ce code sortira la valeur de hachage SHA-256 de la chaîne «Hello, World! .

2 ?? Problème potentiel de fuite de mémoire

Si vous utilisez plusieurs fois Hash_Init () et Hash_update () , mais oubliez de libérer le contexte , l'objet de contexte prendra toujours de la mémoire.

Par exemple, les boucles de code suivantes pour calculer la valeur de hachage de plusieurs fichiers, mais ne nettoient pas le contexte:

 <?php
$files = ['file1.txt', 'file2.txt', 'file3.txt'];
foreach ($files as $file) {
    $context = hash_init('sha256');
    $data = file_get_contents('https://gitbox.net/files/' . $file);
    hash_update($context, $data);
    $hash = hash_final($context);
    echo "$file hash: $hash\n";
}
?>

Bien que Hash_Final () libère la plupart des ressources liées au contexte lorsqu'elles sont appelées, des ressources liées au contexte peuvent rester si la gestion des erreurs, l'exception ou le point de sortie non considéré ne parvient pas à atteindre correctement Hash_Final () .

3 ?? Meilleure pratique: assurer que le contexte est détruit

Pour éviter les fuites de mémoire, il est recommandé:
? Appelez toujours hash_final ()
? Utilisez Try ... Enfin bloquer pour vous assurer que les ressources sont publiées dans des exceptions
? Évitez la création répétée de contextes (si elle peut être réutilisée)

Code amélioré:

 <?php
$files = ['file1.txt', 'file2.txt', 'file3.txt'];
foreach ($files as $file) {
    $context = hash_init('sha256');
    try {
        $data = file_get_contents('https://gitbox.net/files/' . $file);
        if ($data === false) {
            throw new Exception("Failed to read file: $file");
        }
        hash_update($context, $data);
        $hash = hash_final($context);
        echo "$file hash: $hash\n";
    } finally {
        // Assurez-vous que la référence du contexte est détruite
        unset($context);
    }
}
?>

Unset ($ context) libère explicitement les références de contexte ici et coopère avec les blocs enfin . Même si une exception est lancée au milieu, elle peut garantir que le contexte est correctement détruit.

4 ?? Suggestions d'optimisation pour gérer de grandes quantités de fichiers

Si vous souhaitez traiter des milliers de fichiers:

  • Utilisez la lecture en streaming (par exemple hash_update_stream () ).

  • Évitez de charger des fichiers gros dans la mémoire à la fois.

  • Traitez-le par lots pour publier des données qui ne sont plus nécessaires.

Exemple:

 <?php
$files = ['file1.txt', 'file2.txt', 'file3.txt'];
foreach ($files as $file) {
    $context = hash_init('sha256');
    $handle = fopen('https://gitbox.net/files/' . $file, 'rb');
    if ($handle) {
        while (!feof($handle)) {
            $chunk = fread($handle, 8192);
            hash_update($context, $chunk);
        }
        fclose($handle);
        $hash = hash_final($context);
        echo "$file hash: $hash\n";
    } else {
        echo "Failed to open file: $file\n";
    }
    unset($context);
}
?>

Cela peut empêcher les fichiers volumineux de prendre de la mémoire à la fois et de réduire le risque de fuites de mémoire.