следующая программа вызывает утечку памяти? - PullRequest
0 голосов
/ 30 июня 2019

Я выполнял этот код с помощью valgrind, и valgrind показывает, что утечек памяти нет, несмотря на то, что я не закрыл fd_read, почему это так?

edit:

этот вопрос появился на одном из моих экзаменов, по словам моего профессора, правильный ответ - утечка памяти в этой программе.утечка дескрипторов файлов считается утечкой памяти?

   int main(int argc,char** argv){
     int fds[2];
     int fd_read,fd_write;
     if(pipe(fds)==-1){
       perror("Error");
       exit(1);
     }
     fd_read=fds[0];
     fd_write=fds[1];
     close(1);
     dup(fd_write);
     close(fd_write);
     printf("Done");
     return 0;
   }

Ответы [ 3 ]

3 голосов
/ 30 июня 2019

Вызов open, pipe или dup для «выделения» низкоуровневых целочисленных файловых дескрипторов не выделяет никакой пользовательской памяти и, следовательно, не является утечкой памяти, если они не закрыты.

Теперь, с учетом вышесказанного, можно сказать, что эта программа «пропускает» файловые дескрипторы, и это еще один вид утечки ресурсов, который может быть проблемой в долго работающих программах, хотя по какой-либо причине она обычно не заканчивается почти такая же проблема на практике.

(И, конечно же, в любой нормальной операционной системе дескрипторы открытых файлов окончательно закрываются при выходе, точно так же, как все еще выделенная память эффективно, но окончательно освобождается. Так что почти никто не беспокоится об утечках fd в не долго работающих программах .)

2 голосов
/ 30 июня 2019

В вашем случае нет утечки памяти, в основном потому, что open - это системный вызов.Если бы были утечки, valgrind все равно указывал бы на них.

Тем не менее, открытие файлов может выделять память в низкоуровневых библиотеках (скажем, вы вызываете fopen вместо open), главным образом для хранения дескриптора'на самих файлах.

В конце концов, на обычных ОС ядро ​​может закрыть файлы, которые вы, возможно, открыли, и вернуть память, которую вы, возможно, забыли освободить при выходе, так что можно было быИнтересно, кого это волнует?Обычно считается плохой практикой не убирать вещи перед уходом, даже если в конце концов это не очень опасно.

Вы можете отслеживать оставленные нераскрытыми файлы, используя:

valgrind --track-fds=yes ./a.out

В вашем случаеЯ получаю:

==30758== Memcheck, a memory error detector
==30758== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==30758== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info
==30758== Command: ./a.out
==30758== 
==30758== 
==30758== FILE DESCRIPTORS: 7 open at exit.
==30758== Open file descriptor 1:
==30758==    at 0x4F26637: dup (in /usr/lib64/libc-2.27.so)
==30758==    by 0x4006A9: main (in a.out)
==30758== 
==30758== Open file descriptor 3:
==30758==    at 0x4F266C7: pipe (in /usr/lib64/libc-2.27.so)
==30758==    by 0x400670: main (in a.out)
==30758== 
==30758== Open file descriptor 38: /usr/share/applications/org.kde.akonadiimportwizard.desktop
==30758==    <inherited from parent>
==30758== 
==30758== Open file descriptor 27:
==30758==    <inherited from parent>
==30758== 
==30758== Open file descriptor 26:
==30758==    <inherited from parent>
==30758== 
==30758== Open file descriptor 2: /dev/pts/16
==30758==    <inherited from parent>
==30758== 
==30758== Open file descriptor 0: /dev/pts/16
==30758==    <inherited from parent>
==30758== 
==30758== 
==30758== HEAP SUMMARY:
==30758==     in use at exit: 0 bytes in 0 blocks
==30758==   total heap usage: 1 allocs, 1 frees, 4,096 bytes allocated
==30758== 
==30758== All heap blocks were freed -- no leaks are possible
==30758== 
==30758== For counts of detected and suppressed errors, rerun with: -v
==30758== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
1 голос
/ 30 июня 2019

Поскольку у вас нет утечки памяти, у вас просачиваются файловые дескрипторы. Valgrind не отслеживает их, поэтому не показывает, что вы их пропускаете.

Если у вас был длительный процесс, который создавал множество каналов или открывал множество файлов и забыл закрыть их, у вас могут не хватить файловых дескрипторов для этого процесса. Ограничение устанавливается системным администратором и обычно составляет около 1024 или более. После этого канал или системные вызовы вернут -1, чтобы сообщить об ошибке с ошибкой ENFILE.

...