2008-10-09 5 views

Répondre

7

getpwnam()ne pas souffrir de fuite de mémoire. En effet, les appels ultérieurs écraseront son tampon interne statique.

Ce type de fonctions sont à la place non rentrante et donc non-thread-safe. Paul a suggéré l'utilisation de getpwnam_r() qui est la version réentrante, qui peut être utilisée en toute sécurité dans un contexte multithread. Cela dit, les fuites de mémoire sont causées par les appels système qui allouent de la mémoire au moyen de malloc() et laissent l'application à la mémoire free() une fois que les données renvoyées ont été utilisées.

Dans ces cas, l'idiome RAII est conseillé afin de ne pas oublier de libérer la mémoire allouée - voir exception sécurité. std::tr1::shared_ptr<> est également un moyen viable: Pour le shared_ptr un suppresseur personnalisé doit être fourni à free() le pointeur brut lorsque le shared_ptr sort de la portée.

Dans cette perspective certaines fonctions dangereuses sont scandir(), asprintf(), vasprintf() etc.

+0

Oh, bonne réponse. Si je pouvais vous transférer la «réponse acceptée», je le ferais. –

+0

@Nicola, merci de marquer votre réponse comme acceptée –

+0

La réponse est conceptuellement correcte mais ce n'est pas ce qui se passe avec getpwnam ou getpwnam_r. En interne, libc (pas le code utilisateur) alloue dynamiquement des données nss, qui ne sont jamais libérées. Il n'y a aucun moyen de résoudre ceci dans le code utilisateur avec n'importe quel idiome, parce que le problème est dans la libc. Voir: http://sourceware.org/bugzilla/show_bug.cgi?id=2314 – hdante

3

Utilisez getpwnam_r.

2

Je ne pense pas qu'il y ait une solution de contournement. Les réponses ci-dessus ne permettent pas, voir:

[email protected]:~/dev/tryouts$ uname -a 
Linux senap 3.2.0-24-generiC#39-Ubuntu SMP Mon May 21 16:52:17 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux 
[email protected]:~/dev/tryouts$ cat getpwnam-leak.c 
#include <sys/types.h> 
#include <pwd.h> 

extern void __libc_freeres(void); 

int main() 
{ 
    char buf[1024]; 
    struct passwd pw, *result; 
    getpwnam_r("root", &pw, buf, sizeof(buf), &result); 
    __libc_freeres(); 
} 
[email protected]:~/dev/tryouts$ valgrind --leak-check=full ./getpwnam-leak 
==6951== Memcheck, a memory error detector 
==6951== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al. 
==6951== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info 
==6951== Command: ./getpwnam-leak 
==6951== 
==6951== 
==6951== HEAP SUMMARY: 
==6951==  in use at exit: 300 bytes in 11 blocks 
==6951== total heap usage: 69 allocs, 58 frees, 9,234 bytes allocated 
==6951== 
==6951== 300 (60 direct, 240 indirect) bytes in 1 blocks are definitely lost in loss record 11 of 11 
==6951== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==6951== by 0x4F35D94: nss_parse_service_list (nsswitch.c:678) 
==6951== by 0x4F36855: __nss_database_lookup (nsswitch.c:175) 
==6951== by 0x55F32A4: ??? 
==6951== by 0x4EEF1AC: [email protected]@GLIBC_2.2.5 (getXXbyYY_r.c:256) 
==6951== by 0x400607: main (in /home/daniel/dev/tryouts/getpwnam-leak) 
==6951== 
==6951== LEAK SUMMARY: 
==6951== definitely lost: 60 bytes in 1 blocks 
==6951== indirectly lost: 240 bytes in 10 blocks 
==6951==  possibly lost: 0 bytes in 0 blocks 
==6951== still reachable: 0 bytes in 0 blocks 
==6951==   suppressed: 0 bytes in 0 blocks 
==6951== 
==6951== For counts of detected and suppressed errors, rerun with: -v 
==6951== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 2 from 2) 
[email protected]:~/dev/tryouts$ 
0

Pour résoudre ce problème le faire:

sudo sed -i s/compat/files/g /etc/nsswitch.conf 

Il semble que cela est dû à cause d'un bogue dans libnss_compat. Plus d'infos au bugs.debian.org.

Questions connexes