[SOLVED]valgrind: still reachable
Вопрос: это linux «лениво» освобождает память, или программист я чего-то не освободил?
Ответ: память теоретически может быть освобождена, но не освобождена. Т.е. программа не освобождает память, а оставляет это ос.
Нет кода – нет ответа.

«still reachable» means your program is probably ok – it didn’t free some memory it could have. This is quite common and often reasonable. Don’t use —show-reachable=yes if you don’t want to see these reports.
Rerun with —leak-check=full to see details of leaked memory
it didn’t free some memory it could have
Программа не освободила память, которую могла иметь? Не понимаю.
Т.е. память была выделена, но не была освобождена? Т.е. проблема в коде, и какая-то память выделяется, но не освобождается?
Сформулирую иначе: возможно ли, что каждая выделенная в куче память освобождается в коде программы, но still reachable не нуль?

Если выделение памяти произошло в библиотеке, то возможно.
Сформулирую иначе: возможно ли, что каждая выделенная в куче память освобождается в коде программы, но still reachable не нуль?
Если выделение памяти произошло в библиотеке, то возможно.
Ясно. Возможно ли, что какая-то выделенная в коде программы память не освобождается в коде программы, но:

Тоже может быть. Где-то остаётся указатель достижимый из глобальной памяти или статической переменной. —leak-check=full —show-reachable=yes должно показать, о какой именно памяти идёт речь.
still reachable означает что указатель на память не утерян, память может быть теоритически освобождена, но она не освобождена.
P.S. это «типа норм» считается, например, PVS-Studio говорили что они только выделяют память, а освобождает сама система, после того как программа завершит анализ файла. Ещё Уолтер Брайт говорил, что в его dmd dlang compiler память только выделяется, а освободится системой, и это одна из фич, которая позволяет компилятору D быстрее собирать код, чем другим компиляторам…
still reachable означает что указатель на память не утерян, память может быть теоритически освобождена, но она не освобождена.
Вопрос по работе Valgrind
(Отредактирован) При запуске приложения под Valgrind функция sigprocmask() завершается с ошибкой, в то время, как при обычном запуске работает и возвращает валидное значение. С чем это может быть связано?
Если кто может, объясните, пожалуйста, на пальцах, что означает «still reachable» в результатах работы Valgrind? Из прочтенного — это еще доступные ресурсы, которые могут быть освобождены, однако, если учесть, что демон досрочно завершился, почему они доступны? Это могут быть переменные, объявленные в данном модуле как extern?
Заранее извиняюсь, если вопросы покажутся праздными, осваиваю Valgrind c наскока в короткий срок, хочется разобраться. Не откажусь от ссылок на подробную информацию, освещающую эти вопросы.
![]()
- Приложение должно работать, как обычно, но медленнее. Но довольно часто при использовании valgrind проявляют себя ошибки, которые в обычной программе остались незамеченными (из-за случайности). Например, попытка использования памяти, которую только что освободили.
- still reachable означает, что к моменту завершения программы вы не сделали delete для каких-то указателей, но сами указатели еще остались (т.е. можно было освободить память). Это может быть из-за того, что ваша программа упала, а не завершилась нормально
Не имеет значения, каким этот показатель будет после завершения программы, потому что вся выделенная память все равно вернется операционной системе. Но то, что где-то в программе накопилась неучтенная память — не очень хорошо.
Пример: демон раз в N секунд выполняет какое-то действие. Допустим, он должен хранить историю последних десяти действий. Тогда у него будет такой алгоритм работы:
- Что-то сделать.
- Если записей больше десяти, удалить одну
- Добавить запись о текущем действии в историю
Если случайно сделать ошибку во втором пункте, история (и вообще, количество выделенной программе памяти) будет бесконечно расти. Но вся эта память будет still reacable, потому что, теоретически, ее можно освободить.
Я бы начал не с этого. Лучше сначала написать небольшой скрипт, который будет раз в N секунд читать данные (в основном, VmRSS) из /proc/[pid]/status и дал бы программе поработать какое-то время. Потом строите график, и все сразу становится видно: если портебление памяти растет, надо браться за valgrind и искать причины, если достаточно стабильно — фиг с ним.
Valgrind заявляет, что существует неизведанная память. Это плохо?
Valgrind дает мне следующую сводку утечки моего кода. Однако я освободил всю занятую память. Это плохо или это нормально? Моя программа находится в c.
== 3513 == РЕЗЮМЕ УТЕЧКИ:
== 3513 == точно потеряно: 0 байт в 0 блоках.
== 3513 == возможно потеряно: 0 байт в 0 блоках.
== 3513 == все еще достижимо: 568 байт в 1 блоке.
== 3513 == подавлено: 0 байт в 0 блоках.
7 ответов
Сообщение valgrind still reachable: 568 bytes in 1 blocks. означает, что в вашем приложении была освобождена память, которая все еще «достижима», что означает, что у вас все еще есть указатель на нее. При выключении это, вероятно, означает какую-то глобальную переменную. Однако, поскольку количество байтов «определенно утечка» или «вероятно утечка» равно нулю, это условие совершенно неопасно. Не беспокойся об этом.
Все еще доступная память означает, что на нее указывает глобальный или статический указатель. Что вы хотите сделать, так это запустить valgrind с —show-reachable=yes , чтобы убедиться, что это проблема.
Часто это безвредно и исходит из такой функции:
Этот malloc по-прежнему будет доступен. Но независимо от того, сколько раз вызывается foo, вы выделяете буфер ровно один раз, так что не будет никакого вреда, если не освободить его.
Но рассмотрим такую функцию:
Каждый раз, когда вызывается эта функция, выделяется другой узел. В то время как вы можете утечь только несколько узлов для своих тестовых прогонов, в производственном цикле вы можете утечь достаточно, чтобы у вас закончилась память.
Один из способов определить разницу — это увидеть, всегда ли при разных запусках происходит утечка одной и той же памяти или утечка большего количества памяти — это тестовые запуски с большими входными данными.
Но опять же, если вы хотите быть в безопасности, используйте —show-reachable=yes и посмотрите, что происходит.
Они не просочились и не о чем беспокоиться. Вероятно, память была выделена библиотекой C. Если вы действительно хотите знать, где они были размещены, запустите —leak-check=full —show-reachable=yes .
Если вы уверены, что «освободили всю память, занятую неправильно», тогда нет ничего плохого. Вы не несете прямой ответственности за утечки памяти в компонентах от других сторон, даже если вам, возможно, часто придется их обходить.
Отчеты valgrind не дают нам достаточно информации, чтобы помочь вам.
Я много раз видел, как инструменты проверки памяти дают ложные срабатывания, но у меня нет прямого опыта работы с самим valgrind.
Он дает вам адрес блока? иногда можно многому научиться, посмотрев, какие данные находятся в этих 568 байтах.
Хм, 568 байт, это примерно размер строки Unicode MAX_PATH.
Было бы неплохо обнулить указатели, которые были free () ‘ed, что привело бы к сбою при (неправильной) попытке разыменовать их снова.
Лично я всегда забываю и проверяю, например valgrind make test , который всегда добавляет как минимум пару дополнительных все еще доступных байтов . Убедитесь, что ваше приложение запускается непосредственно valgrind . 🙂
Valgrind Frequently Asked Questions
The «Val» as in the word «value». The «grind» is pronounced with a short ‘i’ — ie. «grinned» (rhymes with «tinned») rather than «grined» (rhymes with «find»).
Don’t feel bad: almost everyone gets it wrong at first.
From Nordic mythology. Originally (before release) the project was named Heimdall, after the watchman of the Nordic gods. He could «see a hundred miles by day or night, hear the grass growing, see the wool growing on a sheep’s back», etc. This would have been a great name, but it was already taken by a security package «Heimdal».
Keeping with the Nordic theme, Valgrind was chosen. Valgrind is the name of the main entrance to Valhalla (the Hall of the Chosen Slain in Asgard). Over this entrance there resides a wolf and over it there is the head of a boar and on it perches a huge eagle, whose eyes can see to the far regions of the nine worlds. Only those judged worthy by the guardians are allowed to pass through Valgrind. All others are refused entrance.
It’s not short for «value grinder», although that’s not a bad guess.
2. Compiling, installing and configuring
It’s probably a bug in ‘make’. Some, but not all, instances of version 3.79.1 have this bug, see this. Try upgrading to a more recent version of ‘make’. Alternatively, we have heard that unsetting the CFLAGS environment variable avoids the problem.
You need to install the glibc-static-devel package.
3. Valgrind aborts unexpectedly
When the program exits, Valgrind runs the procedure __libc_freeres in glibc. This is a hook for memory debuggers, so they can ask glibc to free up any memory it has used. Doing that is needed to ensure that Valgrind doesn’t incorrectly report space leaks in glibc.
The problem is that running __libc_freeres in older glibc versions causes this crash.
Workaround for 1.1.X and later versions of Valgrind: use the —run-libc-freeres=no option. You may then get space leak reports for glibc allocations (please don’t report these to the glibc people, since they are not real leaks), but at least the program runs.
If Memcheck (the memory checker) shows any invalid reads, invalid writes or invalid frees in your program, the above may happen. Reason is that your program may trash Valgrind’s low-level memory manager, which then dies with the above assertion, or something similar. The cure is to fix your program so that it doesn’t do any illegal memory accesses. The above failure will hopefully go away after that.
One possibility is that your program has a bug and erroneously jumps to a non-code address, in which case you’ll get a SIGILL signal. Memcheck may issue a warning just before this happens, but it might not if the jump happens to land in addressable memory.
Another possibility is that Valgrind does not handle the instruction. If you are using an older Valgrind, a newer version might handle the instruction. However, all instruction sets have some obscure, rarely used instructions. Also, on amd64 there are an almost limitless number of combinations of redundant instruction prefixes, many of them undocumented but accepted by CPUs. So Valgrind will still have decoding failures from time to time. If this happens, please file a bug report.
Valgrind can handle dynamically generated code, so long as none of the generated code is later overwritten by other generated code. If this happens, though, things will go wrong as Valgrind will continue running its translations of the old code (this is true on x86 and amd64, on PowerPC there are explicit cache flush instructions which Valgrind detects and honours). You should try running with —smc-check=all in this case. Valgrind will run much more slowly, but should detect the use of the out-of-date code.
Alternatively, if you have the source code to the JIT compiler you can insert calls to the VALGRIND_DISCARD_TRANSLATIONS client request to mark out-of-date code, saving you from using —smc-check=all .
Apart from this, in theory Valgrind can run any Java program just fine, even those that use JNI and are partially implemented in other languages like C and C++. In practice, Java implementations tend to do nasty things that most programs do not, and Valgrind sometimes falls over these corner cases.
If your Java programs do not run under Valgrind, even with —smc-check=all , please file a bug report and hopefully we’ll be able to fix the problem.
4. Valgrind behaves unexpectedly
First of all: relax, it’s probably not a bug, but a feature. Many implementations of the C++ standard libraries use their own memory pool allocators. Memory for quite a number of destructed objects is not immediately freed and given back to the OS, but kept in the pool(s) for later re-use. The fact that the pools are not freed at the exit of the program cause Valgrind to report this memory as still reachable. The behaviour not to free pools at the exit could be called a bug of the library though.
Using GCC, you can force the STL to use malloc and to free memory as soon as possible by globally disabling memory caching. Beware! Doing so will probably slow down your program, sometimes drastically.
With GCC 2.91, 2.95, 3.0 and 3.1, compile all source using the STL with -D__USE_MALLOC . Beware! This was removed from GCC starting with version 3.3.
With GCC 3.2.2 and later, you should export the environment variable GLIBCPP_FORCE_NEW before running your program.
With GCC 3.4 and later, that variable has changed name to GLIBCXX_FORCE_NEW .
There are other ways to disable memory pooling: using the malloc_alloc template with your objects (not portable, but should work for GCC) or even writing your own memory allocators. But all this goes beyond the scope of this FAQ. Start by reading http://gcc.gnu.org/onlinedocs/libstdc++/faq/index.html#4_4_leak if you absolutely want to do that. But beware: allocators belong to the more messy parts of the STL and people went to great lengths to make the STL portable across platforms. Chances are good that your solution will work on your platform, but not on others.
If they’re not long enough, use —num-callers to make them longer.
If they’re not detailed enough, make sure you are compiling with -g to add debug information. And don’t strip symbol tables (programs should be unstripped unless you run ‘strip’ on them; some libraries ship stripped).
Also, for leak reports involving shared objects, if the shared object is unloaded before the program terminates, Valgrind will discard the debug information and the error message will be full of . entries. If you use the option —keep-debuginfo=yes , then Valgrind will keep the debug information in order to show the stack traces, at the price of increased memory. An alternate workaround is to avoid calling dlclose on these shared objects.
Also, -fomit-frame-pointer and -fstack-check can make stack traces worse.
Some example sub-traces:
With debug information and unstripped (best):
With no debug information, unstripped:
With no debug information, stripped:
With debug information and -fomit-frame-pointer:
A leak error message involving an unloaded shared object:
Occasionally Valgrind stack traces get the wrong function names. This is caused by glibc using aliases to effectively give one function two names. Most of the time Valgrind chooses a suitable name, but very occasionally it gets it wrong. Examples we know of are printing bcmp instead of memcmp , index instead of strchr , and rindex instead of strrchr .
When a program runs under Valgrind, its environment is slightly different to when it runs natively. For example, the memory layout is different, and the way that threads are scheduled is different.
Most of the time this doesn’t make any difference, but it can, particularly if your program is buggy. For example, if your program crashes because it erroneously accesses memory that is unaddressable, it’s possible that this memory will not be unaddressable when run under Valgrind. Alternatively, if your program has data races, these may not manifest under Valgrind.
There isn’t anything you can do to change this, it’s just the nature of the way Valgrind works that it cannot exactly replicate a native execution environment. In the case where your program crashes due to a memory error when run natively but not when run under Valgrind, in most cases Memcheck should identify the bad memory operation.
There are two possible causes of this.
First, by default, Valgrind only traces the top-level process. So if your program spawns children, they won’t be traced by Valgrind by default. Also, if your program is started by a shell script, Perl script, or something similar, Valgrind will trace the shell, or the Perl interpreter, or equivalent.
To trace child processes, use the —trace-children=yes option.
If you are tracing large trees of processes, it can be less disruptive to have the output sent over the network. Give Valgrind the option —log-socket=127.0.0.1:12345 (if you want logging output sent to port 12345 on localhost ). You can use the valgrind-listener program to listen on that port:
Obviously you have to start the listener process first. See the manual for more details.
Second, if your program is statically linked, most Valgrind tools will only work well if they are able to replace certain functions, such as malloc , with their own versions. By default, statically linked malloc functions are not replaced. A key indicator of this is if Memcheck says:
when you know your program calls malloc . The workaround is to use the option —soname-synonyms=somalloc=NONE or to avoid statically linking your program.
There will also be no replacement if you use an alternative malloc library such as tcmalloc, jemalloc, . In such a case, the option —soname-synonyms=somalloc=zzzz (where zzzz is the soname of the alternative malloc library) will allow Valgrind to replace the functions.
Unfortunately, Memcheck doesn’t do bounds checking on global or stack arrays. We’d like to, but it’s just not possible to do in a reasonable way that fits with how Memcheck works. Sorry.
5. Miscellaneous
Yes! Use the —gen-suppressions=yes feature to spit out suppressions automatically for you. You can then edit them if you like, eg. combining similar automatically generated suppressions using wildcards like ‘*’ .
If you really want to write suppressions by hand, read the manual carefully. Note particularly that C++ function names must be mangled (that is, not demangled).
The details are in the Memcheck section of the user manual.
«definitely lost» means your program is leaking memory — fix those leaks!
«indirectly lost» means your program is leaking memory in a pointer-based structure. (E.g. if the root node of a binary tree is «definitely lost», all the children will be «indirectly lost».) If you fix the «definitely lost» leaks, the «indirectly lost» leaks should go away.
«possibly lost» means your program is leaking memory, unless you’re doing unusual things with pointers that could cause them to point into the middle of an allocated block; see the user manual for some possible causes. Use —show-possibly-lost=no if you don’t want to see these reports.
«still reachable» means your program is probably ok — it didn’t free some memory it could have. This is quite common and often reasonable. Don’t use —show-reachable=yes if you don’t want to see these reports.
«suppressed» means that a leak error has been suppressed. There are some suppressions in the default suppression files. You can ignore suppressed errors.
Prior to version 3.4.0, the answer was «we don’t know how to do it without huge performance penalties». As of 3.4.0, try using the —track-origins=yes option. It will run slower than usual, but will give you extra information about the origin of uninitialised values.
Or if you want to do it the old fashioned way, you can use the client request VALGRIND_CHECK_VALUE_IS_DEFINED to help track these errors down — work backwards from the point where the uninitialised error occurs, checking suspect values until you find the cause. This requires editing, compiling and re-running your program multiple times, which is a pain, but still easier than debugging the problem without Memcheck’s help.
As for eager reporting of copies of uninitialised memory values, this has been suggested multiple times. Unfortunately, almost all programs legitimately copy uninitialised memory values around (because compilers pad structs to preserve alignment) and eager checking leads to hundreds of false positives. Therefore Memcheck does not support eager checking at this time.
No. The environment that Valgrind provides for running programs is significantly different to that for normal programs, e.g. due to different layout of memory. Therefore Valgrind has to have full control from the very start.
It is possible to achieve something like this by running your program without any instrumentation (which involves a slow-down of about 5x, less than that of most tools), and then adding instrumentation once you get to a point of interest. Support for this must be provided by the tool, however, and Callgrind is the only tool that currently has such support. See the instructions on the callgrind_control program for details.
6. How To Get Further Assistance
Read the appropriate section(s) of the Valgrind Documentation.
Search the valgrind-users mailing list archives, using the group name gmane.comp.debugging.valgrind .
If you think an answer in this FAQ is incomplete or inaccurate, please e-mail valgrind@valgrind.org.
If you have tried all of these things and are still stuck, you can try mailing the valgrind-users mailing list. Note that an email has a better change of being answered usefully if it is clearly written. Also remember that, despite the fact that most of the community are very helpful and responsive to emailed questions, you are probably requesting help from unpaid volunteers, so you have no guarantee of receiving an answer.