How to interpret Valgrind output - c++

Valgrind yields the following message block:
1,065,024 bytes in 66,564 blocks are definitely lost in loss record 21 of 27
at 0x4C2B800: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
by 0x40CA21: compute(Parameters&, Array<double>&) [clone .constprop.71] (array.hpp:135)
by 0x403E70: main (main.cpp:374)
How to read this message?
main.cpp line 374 reads:
results[index] = compute(parameters, weights);
Is memory leaked exactly at line 374 of main.cpp? Is it leaked in compute() or maybe at assignment/indexing into results?

Is memory leaked exactly at line 374 of main.cpp?
No. It just shows the line number in main where the call was made that ultimately leads to the function and line where the memory was allocated.
Is it leaked in compute() or maybe at assignment/indexing into results?
It says that memory was allocated in compute() but was not deallocated in the program before the program exited. That's what constitutes a memory leak.

Related

How can I find what is causing my memory allocation error when Valgrind gives me "the impossible happened" [duplicate]

Valgrind yields the following message block:
1,065,024 bytes in 66,564 blocks are definitely lost in loss record 21 of 27
at 0x4C2B800: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
by 0x40CA21: compute(Parameters&, Array<double>&) [clone .constprop.71] (array.hpp:135)
by 0x403E70: main (main.cpp:374)
How to read this message?
main.cpp line 374 reads:
results[index] = compute(parameters, weights);
Is memory leaked exactly at line 374 of main.cpp? Is it leaked in compute() or maybe at assignment/indexing into results?
Is memory leaked exactly at line 374 of main.cpp?
No. It just shows the line number in main where the call was made that ultimately leads to the function and line where the memory was allocated.
Is it leaked in compute() or maybe at assignment/indexing into results?
It says that memory was allocated in compute() but was not deallocated in the program before the program exited. That's what constitutes a memory leak.

Valgrind error with new array [duplicate]

I am getting an invalid read error when the src string ends with \n, the error disappear when i remove \n:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (void)
{
char *txt = strdup ("this is a not socket terminated message\n");
printf ("%d: %s\n", strlen (txt), txt);
free (txt);
return 0;
}
valgrind output:
==18929== HEAP SUMMARY:
==18929== in use at exit: 0 bytes in 0 blocks
==18929== total heap usage: 2 allocs, 2 frees, 84 bytes allocated
==18929==
==18929== All heap blocks were freed -- no leaks are possible
==18929==
==18929== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
==18929==
==18929== 1 errors in context 1 of 1:
==18929== Invalid read of size 4
==18929== at 0x804847E: main (in /tmp/test)
==18929== Address 0x4204050 is 40 bytes inside a block of size 41 alloc'd
==18929== at 0x402A17C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==18929== by 0x8048415: main (in /tmp/test)
==18929==
==18929== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
How to fix this without sacrificing the new line character?
It's not about the newline character, nor the printf format specifier. You've found what is arguably a bug in strlen(), and I can tell you must be using gcc.
Your program code is perfectly fine. The printf format specifier could be a little better, but it won't cause the valgrind error you are seeing. Let's look at that valgrind error:
==18929== Invalid read of size 4
==18929== at 0x804847E: main (in /tmp/test)
==18929== Address 0x4204050 is 40 bytes inside a block of size 41 alloc'd
==18929== at 0x402A17C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==18929== by 0x8048415: main (in /tmp/test)
"Invalid read of size 4" is the first message we must understand. It means that the processor ran an instruction which would load 4 consecutive bytes from memory. The next line indicates that the address attempted to be read was "Address 0x4204050 is 40 bytes inside a block of size 41 alloc'd."
With this information, we can figure it out. First, if you replace that '\n' with a '$', or any other character, the same error will be produced. Try it.
Secondly, we can see that your string has 40 characters in it. Adding the \0 termination character brings the total bytes used to represent the string to 41.
Because we have the message "Address 0x4204050 is 40 bytes inside a block of size 41 alloc'd," we now know everything about what is going wrong.
strdup() allocated the correct amount of memory, 41 bytes.
strlen() attempted to read 4 bytes, starting at the 40th, which would extend to a non-existent 43rd byte.
valgrind caught the problem
This is a glib() bug. Once upon a time, a project called Tiny C Compiler (TCC) was starting to take off. Coincidentally, glib was completely changed so that the normal string functions, such as strlen() no longer existed. They were replaced with optimized versions which read memory using various methods such as reading four bytes at a time. gcc was changed at the same time to generate calls to the appropriate implementations, depending on the alignment of the input pointer, the hardware compiled for, etc. The TCC project was abandoned when this change to the GNU environment made it so difficult to produce a new C compiler, by taking away the ability to use glib for the standard library.
If you report the bug, glib maintainers probably won't fix it. The reason is that under practical use, this will likely never cause an actual crash. The strlen function is reading bytes 4 at a time because it sees that the addresses are 4-byte aligned. It's always possible to read 4 bytes from a 4-byte-aligned address without segfaulting, given that reading 1 byte from that address would succeed. Therefore, the warning from valgrind doesn't reveal a potential crash, just a mismatch in assumptions about how to program. I consider valgrind technically correct, but I think there is zero chance that glib maintainers will do anything to squelch the warning.
The error message seems to indicate that it's strlen that read past the malloced buffer allocated by strdup. On a 32-bit platform, an optimal strlen implementation could read 4 bytes at a time into a 32-bit register and do some bit-twiddling to see if there's a null byte in there. If near the end of the string, there are less than 4 bytes left, but 4 bytes are still read to perform the null byte check, then I could see this error getting printed. In that case, presumably the strlen implementer would know if it's "safe" to do this on the particular platform, in which case the valgrind error is a false positive.

Valgrind Memory Leak Log

In valgrind, we have leak logs like this
==15788== 480 bytes in 20 blocks are definitely lost in loss record 5,016 of 5,501
==20901== 112 (48 direct, 64 indirect) bytes in 2 blocks are definitely lost in loss record 3,501 of 5,122
==20901== 1,375,296 bytes in 78 blocks are possibly lost in loss record 5,109 of 5,122
==20901== Conditional jump or move depends on uninitialised value(s)
==20901== Use of uninitialised value of size 8
In Valgrind's documentation, i couldn't find exact details. Can please somebody explain
I know definitely lost means - the memory allocated is not at all freed. But can what does it mean by "20 blocks" and what it means of "lost in loss record 5,016 of 5,501". And if it says 480 bytes are lost, does it mean for one run in a loop or total ..?
In the Second line ,"112 (48 direct, 64 indirect) bytes in 2 blocks are definitely lost", what does it means "48 direct, 64 indirect".
And i understand the meaning of"possibly lost", but does that mean valgrind is not sure if it's a leak ..?
And regarding the 4th line, i have no idea at all. I checked the call stack provided along with that 4th line. I don't notice any "jump or move".
For the 5th line, it says the uninitialised is in last line of this code snippet. I don't see any uninitialised value here.
char *data = new char[somebigSize];
memset(data, '\0', somebigSize);
int sizeInt = sizeof(int);
int length = 20; //some value obtained
int position = 10;
char *newPtrVar = new char[sizeInt + 1];
memset(newPtrVar, '\0', sizeInt + 1);
memcpy(newPtrVar, &length, sizeInt);
memcpy(&data[position], newPtrVar, sizeInt);
The valgrind manual covers this in detail. It's quite complicated - see the link for full details, but in essence you can have:
"still reachable" (memory that is pointed to by a pointer).
"directly lost" (memory that is not pointed to be any live pointer)
"indirectly lost" (memory that is pointed to by a pointer that is in memory that is "directly lost)
"possibly lost" (memory that is pointed to, but the pointer does not point to the start of the memory).
The last case could be some random pointer, and it could be something like a memory manager that allocates a redzone before the memory returned to the user.

Valgrind results of a "segmentation fault" program

My program (./a.out) encountered with a segmentation fault, so I use Valgrind to check if I can find at which line of code the program corrupts. I got the following output, but I cannot understand them. To me, the most suspicious line of the output is ==17967== Address 0x20687cf80 is 0 bytes inside a block of size 16 alloc'd, does this line means the address 0x20687cf80 is not propoerly allocated a memory block? What can I do to resolve this problem.
I am using a 64-bit linux with 64GB ram.
[root#gpu BloomFilterAndHashTable]# valgrind --tool=memcheck --leak-check=full ./a.out /mnt/disk2/experiments/two_stage_bloom_filter/test/10_10.txt /mnt/disk2/experiments/10M_worstcase_trace/w_10_10.trace 24
==17967== Memcheck, a memory error detector
==17967== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==17967== Using Valgrind-3.6.1 and LibVEX; rerun with -h for copyright info
==17967== Command: ./a.out /mnt/disk2/experiments/two_stage_bloom_filter/test/10_10.txt /mnt/disk2/experiments/10M_worstcase_trace/w_10_10.trace 24
==17967==
9998797 Prefixes loaded! //output of my program
==17967== Warning: set address range perms: large range [0x4201a040, 0x6f423220) (defined)
==17967== Warning: set address range perms: large range [0x9c834040, 0x20687cf40) (undefined)
insertion cost time(us): 173168519 9998797 17.318935 0.057740 //output of my program
==17967== Warning: set address range perms: large range [0x23647d040, 0x25647d040) (defined)
Trace loaded! //output of my program
lookup cost time(us): 5728767367 67108864 85.365286 0.011714 //output of my program
==17967== Mismatched free() / delete / delete []
==17967== at 0x4A055FE: free (vg_replace_malloc.c:366)
==17967== by 0x401B13: hash_table_delete(BloomFilter*, char*) (BloomFilterAndHashTable.cpp:503)
==17967== by 0x402212: main (BloomFilterAndHashTable.cpp:687)
==17967== Address 0x20687cf80 is 0 bytes inside a block of size 16 alloc'd
==17967== at 0x4A05F97: operator new(unsigned long) (vg_replace_malloc.c:261)
==17967== by 0x40146D: hash_table_insert(char*, int, BloomFilter*) (BloomFilterAndHashTable.cpp:293)
==17967== by 0x401DD5: main (BloomFilterAndHashTable.cpp:597)
==17967==
Delete succeeded! //output of my program
deletion cost time(us): 178048113 9998797 17.806953 0.056158 //output of my program
==17967== Warning: set address range perms: large range [0x23647d030, 0x25647d050) (noaccess)
--17967:0:aspacem Valgrind: FATAL: VG_N_SEGMENTS is too low.
--17967:0:aspacem Increase it and rebuild. Exiting now.
[root#gpu BloomFilterAndHashTable]#
The "suspicious" output ==17967== Address 0x20687cf80 is 0 bytes inside a block of size 16 alloc'd means, that there is an allocated block of memory, 16 bytes in size. Address 0x20687cf80 is the address of the very first byte of that block (i.e. it's the address of the whole block). So the line itself does only tell you details about a memory block that is involved in the whole warning.
The warning itself is about a "mismatched free()". The following lines show where the free was called:
==17967== at 0x4A055FE: free (vg_replace_malloc.c:366)
==17967== by 0x401B13: hash_table_delete(BloomFilter*, char*) (BloomFilterAndHashTable.cpp:503)
Meaning, hash_table_delete calls free(). Now, why does valgrind think that this is a mismatch? Because the address of the memory block that gets freed (0x20687cf80) was allocated by operator new, which was called by hash_table_insert:
==17967== at 0x4A05F97: operator new(unsigned long) (vg_replace_malloc.c:261)
==17967== by 0x40146D: hash_table_insert(char*, int, BloomFilter*) (BloomFilterAndHashTable.cpp:293)
This is suspicious. If it is the source of your error is another problem, but you should fix it anyways.

How to print line number for the root cause of memory leak using valgrind 3.7.0?

The output format is displaying stack so its hard to find the root cause.
==21663== Invalid read of size 4
==21663== at 0x4448117: iurcall_init_rlmgt_IsAllAlcapSuccess(Iurcall_Init_CallCtx_t*) (iurcall_init_rlmgt_p.cc:6319)
==21663== by 0x47D98DD: iurcall_init_rlmgt_IsAllAlcapSuccess_Test_return_1_when_edchMacD_flow_ctx_not_exist_and_alcapEstablish_is_FALSE_Test::TestBody() (iurcall_init_rlmgt_p_test.cc:373)
==21663== by 0x8BCAB27: testing::Test::Run() (gmock-gtest-all.cc:3436)
==21663== by 0x8BD1966: testing::internal::TestInfoImpl::Run() (gmock-gtest-all.cc:3655)
==21663== by 0x8BD1AA8: testing::TestCase::Run() (gmock-gtest-all.cc:3761)
==21663== by 0x8BD1D96: testing::internal::UnitTestImpl::RunAllTests() (gmock-gtest-all.cc:5365)
==21663== by 0x8BD1F21: testing::UnitTest::Run() (gmock-gtest-all.cc:5028)
==21663== by 0x4820149: Gtest_initialisation(int, char**) (iurcall_init_gtest_main.cc:49)
==21663== by 0x808E500: main (bosinit_config_template.h:439)
==21663== Address 0xa8190e4 is 44 bytes inside a block of size 56 free'd
This Valgrind output looks incomplete. It should be something like in this question where the second call stack is printed after Address 0xa8190e4 is 44 bytes inside a block of size 56 free'd.
This call stack is the root cause of the problem. It is not a memory leak. You are trying to work with already deallocated object. The second call stack is where the object was deallocated and the first one is where it was used.