setpwent показывает утечку памяти в valgrind - PullRequest
2 голосов
/ 24 июня 2011

Я проверяю свою программу на предмет утечек памяти и повреждений, и у меня возникла проблема с использованием setpwent.Рассмотрим простую программу как:

#include<stdio.h>
#include<stdlib.h>

main()
{
    struct passwd *ent=NULL;
    setpwent();
        while ((ent = getpwent()) != NULL) { }
    endpwent();
}

, когда я запускаю этот кусок кода в valgrind, я получаю следующее:

> valgrind  --track-origins=yes
> --tool=memcheck --leak-check=yes --show-reachable=yes --num-callers=20 --track-fds=yes ./a.out . . . 160 (40 direct, 120 indirect) bytes in 1
> blocks are definitely lost in loss
> record 11 of 11
> ==6471==    at 0x4025BD3: malloc (vg_replace_malloc.c:236)
> ==6471==    by 0x411CA9C: nss_parse_service_list
> (nsswitch.c:622)
> ==6471==    by 0x411D216: __nss_database_lookup (nsswitch.c:164)
> ==6471==    by 0x459BEAB: ???
> ==6471==    by 0x459C1EC: ???
> ==6471==    by 0x411D864: __nss_setent (getnssent_r.c:84)
> ==6471==    by 0x40D304F: setpwent (getXXent_r.c:127)
> ==6471==    by 0x8048469: main (in /root/workspace/cdk-examples/MMC-0.64/a.out)
> ==6471== 
> ==6471== LEAK SUMMARY:
> ==6471==    definitely lost: 40 bytes in 1 blocks
> ==6471==    indirectly lost: 120 bytes in 10 blocks
> ==6471==      possibly lost: 0 bytes in 0 blocks
> ==6471==    still reachable: 0 bytes in 0 blocks
> ==6471==         suppressed: 0 bytes in 0 blocks

Стоит ли мне беспокоиться об этом?Как я могу устранить эту проблему?

Второй вопрос: Нужно ли освободить ввод пароля, как:

main()
{
    struct passwd *ent=NULL;
    setpwent();
        while ((ent = getpwent()) != NULL) {
            free(ent);
        }
        endpwent();
}

спасибо за помощь.

1 Ответ

3 голосов
/ 24 июня 2011

За первый вопрос.Я не думаю, что вам нужно звонить setpwent в любом случае.Это первый вызов getpwent (после запуска процесса или после endpwent), который возвращается к началу.

Вам нужно setpwent, только если вы хотите перемотать после вызоваgetpwent, но без вызова endpwent.

Один set, вероятно, быстрее, чем пара end/get, особенно если, как я подозреваю, весь (или значительная часть) файл можетбыть кэшированным в памяти (a) .


По второму вопросу, нет, вы не освобождаете его.Смотрите здесь .Скорее всего, он будет использовать статический буфер (для однопоточности) или локальное хранилище (для многопоточности).

В обоих случаях сами вызовы управляют буфером, а не вашим кодом (a) .


(a) Интересно, что значения ent, передаваемые обратно, различны на каждой итерации, которая, безусловно, выглядит как отдельные выделения.

Однако, поскольку адреса находятся на расстоянии всего 32 байта, а размер struct pwd составляет 32 байта, это не оставляет места для служебной malloc служебной информации.

Таким образом, служебная информация не является встроенной (маловероятной), или вы фактически работаете с массивом структур, а не с отдельными выделениями.

Следующая программа показывает это в действии:

#include <stdio.h>
#include <stdlib.h>
#include <pwd.h>

int main (void) {
    struct passwd *ent = NULL;
    printf ("ent struct is %d bytes\n", sizeof(*ent));
    while ((ent = getpwent()) != NULL) {
        printf ("pointer is %p, user is %s\n", ent, ent->pw_name);
        // free (ent);
    }
    endpwent();
    return 0;
}

Это выводит:

ent struct is 32 bytes
pointer is 0x4708d0, user is alan
pointer is 0x4708f0, user is bill
pointer is 0x470910, user is carl
pointer is 0x470930, user is dawn
pointer is 0x470950, user is ella
pointer is 0x470970, user is fran

, что и приводит меня к выводам выше.В любом случае, как только я раскомментирую эту строку free в моем коде, я получаю дамп ядра, что дает дополнительную поддержку моей теории.

Теперь я полагаю, что мог бы только что исчезнутьи взглянул на исходный код getpwent, но мне нравится хорошая загадка: -)

...