2016-08-20 3 views
2

В настоящее время я использую функцию fscanf, чтобы проанализировать файл с некоторым символом и точкой плавания. Я подтвердил результаты, распечатав их и проверку памяти с помощью valgrind. Теперь печать правильная, но всегда есть определенно потеря памяти.Функция C fscanf с потерей памяти

Это пример кода:

FILE* table; 
table = fopen("table", "r"); 
double mass; 
while (fscanf(table, %lf ", &mass) != EOF){ 
    printf("mass: %lf\n", mass); 
} 

и Valgrind с --leak-check=full вариант говорит:

==7104== 513 bytes in 1 blocks are definitely lost in loss record 52 of 62 
==7104== at 0x100008EBB: malloc (in /usr/local/Cellar/valgrind/3.11.0/lib/valgrind/vgpreload_memcheck-amd64-darwin.so) 
==7104== by 0x1001EF66C: __parsefloat_buf (in /usr/lib/system/libsystem_c.dylib) 
==7104== by 0x1001ED9EF: __svfscanf_l (in /usr/lib/system/libsystem_c.dylib) 
==7104== by 0x1001E1492: fscanf (in /usr/lib/system/libsystem_c.dylib) 
==7104== by 0x100000F3F: main (in ./prtm) 

Я думаю, что это проблема формата. Я также пытался использовать %f и float, но просто получаю более схожую ошибку. Может ли кто-нибудь сказать мне, что пошло не так?

+6

Вы не закрываем файл. – 2501

+0

Просто для того, чтобы исключить это как возможную причину: вы * сделаете * получите дополнительный отчет о потерях памяти для этого недостающего 'fclose', правильно? (Как следует сообщать в соответствии с http://stackoverflow.com/q/31630583/2564301) И правильно закрывать файл делает * not * заставлять это уходить? – usr2564301

+1

Если вы запустили 'valgrind', и ваш код НЕ выделяет какую-либо память явно, но' valgrind' все еще сообщает, что память используется при выходе, сначала посмотрите на другие вызовы функций, например 'fopen', которые выделяют память для своих собственных использовать. Если вы не выделяете память и не вызываете каких-либо дополнительных функций библиотеки, и у вас все еще есть отчетная память 'valgrind', используемая при выходе, то вероятная причина - это правильные * исключающие * файлы, недоступные в вашей версии' valgrind' для ОС, в которой вы сейчас работаете. Бывает, просто спросите тех, кто работает с mac. –

ответ

3

Хотя вы не fclose(), чтобы опубликовать фрагмент кода, я сомневаюсь, что это вызывает проблемы. В любом случае, убедитесь, что вы fclose() файл.

Функция fscanf, как представляется, выделяет память в своих целях и не освобождает ее при выходе из программы. valgrind обычно знает о такой неизбежной утечке памяти и подавляет выход, потому что по какой-то причине он пропустил это.

Это сообщение не содержит никаких проблем в вашем коде. Сообщенный потерянный блок выделяется версией OS/X fscanf(), как видно из стека вызовов, для его внутреннего анализатора с плавающей запятой __parsefloat_buf.

Точнее, исходный код LibC доступен от http://opensource.apple.com (Libc-763.11/stdio/vfscanf-fbsd.c:965), и блок должен был быть свободен при выходе.

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

#include <stdlib.h> 
#include <pthread.h> 
#include <sys/cdefs.h> 

... 

free(pthread_getspecific(__LIBC_PTHREAD_KEY_PARSEFLOAT)); 
pthread_setspecific(__LIBC_PTHREAD_KEY_PARSEFLOAT, NULL); 

Вместо этого, как отметил Rad Lexus, вы должны сказать Valgrind игнорировать это предупреждение, как показано в этом вопросе: On OSX Valgrind reports this memory leak, Where is it coming from?

+1

Я с вами на этом - но указание на то, как вы можете отличить эту ситуацию (только функции библиотеки в стеке вызовов выделения, никакая документация не говорит вам нужно «освобождать» что-нибудь после «fscanf») из ситуации, когда ваш код действительно делает что-то неправильно, действительно увеличит ответ. – tofro

+1

«Не так много»? Джонатан Леффлер говорит, что вы можете попросить valgrind [игнорировать это] (http://stackoverflow.com/a/9039682/2564301). – usr2564301

+1

Замечание о том, что библиотеки не освобождают выделенную память: для библиотек не всегда возможно/возможно освободить память во время работы программы, для этого нет практического механизма. Они могут добавить обработчик выхода и освободить память перед выходом программы, но ... почему? Нет никакой пользы, вся память программы скоро исчезнет. – hyde