2010-07-05 7 views
6

Quelles sont les implications d'appeler CloseHandle plus d'une fois?Est-il prudent de "fermer deux fois" une poignée à l'aide de CloseHandle?

Les docs disent "vous ne devriez pas" mais je pense que j'ai un cas réaliste avec des tuyaux nommés où une poignée pourrait être fermée à l'extérieur (voir la fin de la poste). CloseHandle lève une exception en mode debug dans ce cas, ce qui me suggère que les développeurs pensent que c'est sérieux, mais que les docs ne sont pas tout à fait clairs.

(Demande polie: S'il vous plaît éviter la réponse "tout simplement pas!" :-). Bien sûr, il faut éviter de fermer un handke plus d'une fois, et bien sûr il y a de bonnes techniques pour vous aider: je ne suis intéressé que par ce qui se passe si vous ne le faites pas).

J'ai entendu des gens suggérer que si la poignée était rapidement réutilisée par le système d'exploitation, vous pourriez finir par fermer une autre poignée différente.

Est-ce possible?

Comment Windows choisit-il de gérer les ID?

Y a-t-il une garantie sur la fréquence à laquelle une valeur de handle sera réutilisée?

(par exemple, TCP garantit qu'un numéro de port ne peut pas être réutilisé dans un certain laps de temps).

Pouvez-vous fermer les poignées à travers les types de poignée? Par exemple, est-ce que je pourrais penser que je ferme une pipe mais que je finis un événement?

Merci!

John

(contexte à ceci:. Je suis en utilisant les pipes nommés dans un modèle client/serveur Il me semble très difficile de faire en sorte que exactement une partie est garantie pour fermer la poignée, par exemple dans un accident de processus J'ai peut-être tort, mais l'exemple de code MSDN me semble permettre au client de fermer le handle partagé, et lorsque le serveur essaie de le fermer, il est déjà fermé).

+0

De quel "handle partagé" parlez-vous? Chaque processus devrait créer * et * fermer son propre handle au (même) tuyau. Comment une poignée finit-elle par être partagée? Hélas, la réponse ** est ** "ne fais pas", mais c'est parce que le handle ne devrait pas être partagé du tout. – shambulator

Répondre

11

assez simple pour vérifier:

HANDLE h = 0; 
h = CreateMutex(NULL, TRUE, NULL); 
printf("%X\n", h); 
CloseHandle(h); 
h = 0; 
h = CreateMutex(NULL, TRUE, NULL); 
printf("%X\n", h); 

Dans mon Windows XP x64 ce produit:

2E8 
2E8 

Donc là vous l'avez.
Contrairement aux ports TCP, les poignées sont recyclées immédiatement.

Répétez cette expérience avec votre API préférée ou un mélange de celles-ci.

+0

+1, Aussi une poignée peut être réutilisée pour n'importe quel objet - peut-être mutex, peut-être quelque chose d'autre. Faire deux fois CloseHandle() peut avoir des conséquences surprenantes. – sharptooth

4

Vous avez probablement la mauvaise image mentale d'un tuyau. Il a deux extrémités, chacune représentée par une poignée différente. Oui, CloseHandle doit être appelé deux fois pour que l'instance de pipe disparaisse. Mais comme ce sont des poignées différentes, cela ne peut jamais poser de problème. Notez également que les instances de handles sont spécifiques au processus. Même s'ils ont la même valeur dans les deux processus, ils ne référencent pas le même point de terminaison.

+0

Hmm peut-être que j'ai mal compris. Mais j'ai certainement vu des problèmes où le client à la pipe ferme le tuyau, et le serveur jette alors une exception "handle invalide" (en mode de débogage). – John

1

Il y a deux choses qui pourraient se produire:

  1. Vous fermez une poignée ouverte par un autre code.Cela n'affecte probablement pas votre code, mais il risque d'être catastrophique pour l'autre code.
  2. Si vous utilisez un débogueur connecté, vous plantez votre application car le système d'exploitation déclenche une exception lorsqu'il détecte la fermeture d'un handle non valide.

Aucun de ceux-ci n'est particulièrement attrayant à mon humble avis.