утечка памяти происходит при запуске кода, который включает popen - PullRequest
0 голосов
/ 15 января 2020

Я отлаживаю простой popen-код с помощью valgrind.

code popen_test. c

#include<stdio.h>
#include <unistd.h>

int main(void)
{
    FILE *fp;

    fp = popen("lsblk", "r");
    if (fp == NULL) {
        return -1;
    }

    pclose(fp);

    return 0;
}

команда для компиляции

g cc -g -O0 popen_test. c

команда для запуска

valgrind --tool = memcheck --num-callers = 30 --trace-children = yes --leak-check = full ./a.out

log

== 5993 == Memcheck, детектор ошибок памяти
== 5993 == Авторские права (C) 2002-2017, и GNU GPL'd, Джулиан Сьюард и др.
== 5993 == Использование Valgrind-3.14.0 и LibVEX; повторно введите -h для получения информации об авторских правах
== 5993 == Команда: ./a.out
== 5993 ==
== 5994 == Memcheck, детектор ошибок памяти
== 5994 == Авторские права (C) 2002-2017 и GNU GPL'd, Джулиан Сьюард и др.
== 5994 == Использование Valgrind-3.14.0 и LibVEX; Перезапустите с -h для получения информации об авторских правах
== 5994 == Команда: / bin / sh - c lsblk
== 5994 ==
== 5995 == Memcheck, детектор ошибок памяти
== 5995 == Авторские права (C) 2002-2017 и GNU GPL'd, Джулиан Сьюард и др.
== 5995 == Использование Valgrind-3.14.0 и LibVEX; для получения информации об авторских правах снова введите -h
== 5995 == Команда: / bin / lsblk
== 5995 ==
== 5995 ==
== 5995 == Процесс завершается с действием по умолчанию сигнала 13 (SIGPIPE)
== 5995 == в 0x4A971E4: запись (запись. c: 26)
== 5995 == в 0x4A43787: _IO_file_write @@ GLIBC_2.17 (fileops. c) : 1188)
== 5995 == от 0x4A42B87: new_do_write (fileops. c: 456)
== 5995 == от 0x4A4482F: _IO_new_do_write (fileops. c: 433)
== 5995 == по 0x4A4482F: _IO_do_write @@ GLIBC_2.17 (fileops. c: 430)
== 5995 == по 0x4A44147: _IO_file_close_it @@ GLIBC_2.17 (fileops. c: 136)
== 5995 == по 0x4A36CE7: fclose @@ GLIBC_2.17 (iofclose. c: 53)
== 5995 == по 0x10EAEB: ??? (in / bin / lsblk)
== 5995 == по 0x4A09CC7: __run_exit_handlers (выход. c: 108)
== 5995 == по 0x4A09E2B: выход (выход. c: 139)
== 5995 == по 0x49F5D27: (ниже основного) (lib c -start. c: 342)
== 5995 ==
== 5995 == РЕЗЮМЕ КАРТЫ:
== 5995 == используется на выходе: 16 735 байтов в 10 блоках
== 5995 == общее использование кучи: 1 136 выделений, 1 126 освобождений, 2 262 873 выделенных байтов
== 5995 ==
== 5995 == 12 639 (12 456 прямых, 183 косвенных) байта в 3 блоках определенно теряются в записи потерь 4 из 4
== 5995 == при 0x484A124: callo c (vg_replace_mallo c. c: 752)
== 5995 == по 0x114ED3: ??? (в / bin / lsblk)
== 5995 == по 0x118153: ??? (в / bin / lsblk)
== 5995 == по 0x10ED6B: ??? (в / bin / lsblk)
== 5995 == по 0x10DC0F: ??? (in / bin / lsblk)
== 5995 == по 0x49F5D23: (ниже основного) (lib c -start. c: 308)
== 5995 ==
== 5995 == РЕЗЮМЕ УТЕЧКИ:
== 5995 == определенно потеряно: 12 456 байт в 3 блоках
== 5995 == потеря косвенно: 183 байта в 6 блоках
== 5995 == возможно потеряно: 0 байт в 0 блоках
== 5995 == все еще достижимо: 4 096 байт в 1 блоках
== 5995 == подавлено: 0 байт в 0 блоках
== 5995 == Доступные блоки (те, на которые указывает указатель был найден) не показываются.
== 5995 == Чтобы увидеть их, перезапустите с: --leak-check = full --show-leak-types = all
== 5995 ==
= = 5995 == Для подсчета обнаруженных и подавленных ошибок, перезапустите с: -v
== 5995 == РЕЗЮМЕ ОШИБОК: 1 ошибка из 1 контекста (подавлено: 0 из 0)
== 5994 ==
== 5994 == РЕЗЮМЕ HEAP:
== 5994 == используется на выходе: 1075 байт в 30 блоках
== 5994 == общее использование кучи: 32 выделения, 2 освобождения, 1211 выделенных байтов
== 5994 ==
== 5994 == РЕЗЮМЕ УТЕЧКИ:
== 5994 == определенно потеряно: 0 байтов в 0 блоках * 1 079 * == 5994 == косвенно потеряно: 0 байтов в 0 блоках
== 5994 == возможно потеряно: 0 байтов в 0 блоках
== 5994 == все еще достижимо: 1075 байтов в 30 блоках
== 5994 == подавлено: 0 байтов в 0 блоках
== 5994 == Доступные блоки (те, на которые был найден указатель) не отображаются.
== 5994 == Чтобы просмотреть их, перезапустите с: --leak-check = full --show-leak-types = all
== 5994 ==
== 5994 == Для подсчета обнаруженных и подавленных ошибок, повторно запустите: -v
== 5994 == РЕЗЮМЕ ОШИБКИ: 0 ошибок из 0 контекстов (исключено: 0 из 0)
== 5993 ==
== 5993 == РЕЗЮМЕ HEAP:
== 5993 == используется на выходе: 0 байтов в 0 блоках
== 5993 == общее использование кучи: 1 выделение, 1 освобождение, выделение 256 байтов
== 5993 ==
== 5993 == Все блоки кучи были освобождены - нет возможны утечки
== 5993 ==
== 5993 == Для подсчета обнаруженных и подавленных ошибок повторно запустите: -v
== 5993 == РЕЗЮМЕ ОШИБОК: 0 ошибок из 0 контекстов (исключено : 0 из 0)

Я вижу, что это приводит к утечке памяти для popen.
Есть ли в моем коде ошибка? или Как использовать valgrind не так?
Не могли бы вы мне помочь?

Спасибо.

Postscript
Я изменил код, чтобы избежать SIGPIPE .

#include<stdio.h>
#include <unistd.h>

int main(void)
{
    FILE *fp;
    char var[256] = {0};

    fp = popen("lsblk", "r");
    if (fp == NULL) {
        return -1;
    }

    while (fgets(var, sizeof(var), fp) != NULL)
    {
        ;
    }

    pclose(fp);

    return 0;
}

== 7778 == Memcheck, детектор ошибок памяти
== 7778 == Авторские права (C) 2002-2017 и GNU GPL'd, Джулиан Сьюард и др.
== 7778 == Использование Valgrind-3.14.0 и LibVEX; повторно введите -h для получения информации об авторских правах
== 7778 == Команда: ./a.out
== 7778 ==
== 7779 == Memcheck, детектор ошибок памяти
== 7779 == Авторские права (C) 2002-2017 и GNU GPL'd, Джулиан Сьюард и др.
== 7779 == Использование Valgrind-3.14.0 и LibVEX; Перезапустите с -h для получения информации об авторских правах
== 7779 == Команда: / bin / sh - c lsblk
== 7779 ==
== 7780 == Memcheck, детектор ошибок памяти
== 7780 == Авторские права (C) 2002-2017 и GNU GPL'd, Джулиан Сьюард и др.
== 7780 == Использование Valgrind-3.14.0 и LibVEX; повторно введите -h для получения информации об авторских правах
== 7780 == Команда: / bin / lsblk
== 7780 ==
== 7780 ==
== 7780 == РЕЗЮМЕ КАРТЫ:
== 7780 == используется на выходе: 12 639 байт в 9 блоках
== 7780 == общее использование кучи: 1136 выделений, 1127 освобождений, 2 262 873 выделенных байтов
== 7780 ==
== 7780 == 12 639 (12 456 прямых, 183 косвенных) байта в 3 блоках определенно теряются в записи потерь 3 из 3
== 7780 == при 0x484A124: callo c (vg_replace_mallo c. c: 752 )
== 7780 == по 0x114ED3: ??? (в / bin / lsblk)
== 7780 == по 0x118153: ??? (в / bin / lsblk)
== 7780 == по 0x10ED6B: ??? (в / bin / lsblk)
== 7780 == по 0x10DC0F: ??? (в / bin / lsblk)
== 7780 == по 0x49F5D23: (ниже основного) (lib c -start. c: 308)
== 7780 ==
== 7780 == РЕЗЮМЕ УТЕЧКИ:
== 7780 == определенно потеряно: 12 456 байт в 3 блоках
== 7780 == косвенно потеряно: 183 байта в 6 блоках
== 7780 == возможно потеряно: 0 байт в 0 блоках
== 7780 == все еще достижимо: 0 байт в 0 блоках
== 7780 == подавлено: 0 байт в 0 блоках
== 7780 ==
== 7780 == Для подсчета обнаруженных и подавленных ошибок, перезапустите с: -v
== 7780 == РЕЗЮМЕ ОШИБОК: 1 ошибок из 1 контекста (подавлено: 0 из 0)
== 7779 ==
== 7779 == КРАТКИЙ ОБЗОР:
== 7779 == используется на выходе: 1075 байт в 30 блоках
== 7779 == общее использование кучи: 32 выделения, 2 освобождения, 1211 выделенных байтов
== 7779 ==
== 7779 == РЕЗЮМЕ УТЕЧКИ:
== 7779 == определенно потеряно: 0 байтов в 0 блоках
== 7779 == косвенно потеряно: 0 байтов в 0 блоках
== 7779 == возможно потеряно: 0 байтов в 0 блоках
== 7779 == все еще достижимо: 1075 байтов в 30 блоках
== 77 79 == подавлено: 0 байтов в 0 блоках
== 7779 == Доступные блоки (те, на которые был найден указатель) не отображаются.
== 7779 == Чтобы просмотреть их, перезапустите с: - проверка на утечку = полная --show-leak-types = all
== 7779 ==
== 7779 == Для подсчета обнаруженных и подавленных ошибок, повторите процедуру с: -v
== 7779 == РЕЗЮМЕ ОШИБКИ: 0 ошибок из 0 контекстов (исключено: 0 из 0)
== 7778 ==
== 7778 == РЕЗЮМЕ HEAP:
== 7778 == используется на выход: 0 байтов в 0 блоках
== 7778 == общее использование кучи: 2 выделения, 2 освобождения, 4 352 байта выделено
== 7778 ==
== 7778 == Все блоки кучи были освобождены - - утечки невозможны
== 7778 ==
== 7778 == Для подсчета обнаруженных и подавленных ошибок повторно запустите: -v
== 7778 == РЕЗЮМЕ ОШИБОК: 0 ошибок из 0 контекстов (исключено: 0 из 0)

SIGPIPE не отображается, но, похоже, происходит утечка памяти в открытом процессе.

1 Ответ

2 голосов
/ 15 января 2020

Нет, ваша программа (в процессе 5993) не протекает.

==5993== HEAP SUMMARY:
==5993== in use at exit: 0 bytes in 0 blocks
==5993== total heap usage: 1 allocs, 1 frees, 256 bytes allocated
==5993==
==5993== All heap blocks were freed -- no leaks are possible

lsblk (в процессе 5995) все еще выделена память, но это нормально, потому что процесс был убит (SIGPIPE ) до завершения программы.

==5995== Process terminating with default action of signal 13 (SIGPIPE)

Процесс получает сигнал SIGPIPE при записи в закрытый канал или сокет. (Стандартный вывод lsblk, в данном случае.)

...