error using valgrind client requests with threads

Hi everyone,

I am playing around with valgrind client memchech requests and found that when using threads, valgrind reports erros that it shouldn't report. Take this example code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//main.cpp
#include <cassert>
#include <thread>
#include <valgrind/memcheck.h>

void func()
{

}

int main()
{
    unsigned int initialErrors_, finalErrors_;
    VALGRIND_DO_ADDED_LEAK_CHECK;
    initialErrors_ = VALGRIND_COUNT_ERRORS;

    std::thread t1(func);
    t1.join();

    VALGRIND_DO_ADDED_LEAK_CHECK;
    finalErrors_ = VALGRIND_COUNT_ERRORS;

    assert(initialErrors_ == finalErrors_);

    return 0;
}


This is an excerpt of the output I get if I execute this with 'valgrind --leak-check=full ./main':

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

288 (+288) bytes in 1 (+1) blocks are possibly lost in loss record 1 of 2
    at 0x4C2FB55: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    by 0x40138A4: allocate_dtv (dl-tls.c:322)
    by 0x40138A4: _dl_allocate_tls (dl-tls.c:539)
    by 0x53DA26E: allocate_stack (allocatestack.c:588)
    by 0x53DA26E: pthread_create@@GLIBC_2.2.5 (pthread_create.c:539)
    by 0x4EF2DC2: std::thread::_M_start_thread(std::shared_ptr<std::thread::_Impl_base>, void (*)()) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
    by 0x4014D7: std::thread::thread<void (&)()>(void (&)()) (thread:137)
    by 0x4010AD: main (main.cpp:16)

 LEAK SUMMARY:
    definitely lost: 0 (+0) bytes in 0 (+0) blocks
    indirectly lost: 0 (+0) bytes in 0 (+0) blocks
      possibly lost: 288 (+288) bytes in 1 (+1) blocks
    still reachable: 72,704 (+0) bytes in 1 (+0) blocks
         suppressed: 0 (+0) bytes in 0 (+0) blocks
 Reachable blocks (those to which a pointer was found) are not shown.
 To see them, rerun with: --leak-check=full --show-leak-kinds=all

main: main.cpp:22: int main(): Assertion `initialErrors_ == finalErrors_' failed.
 



Why am I getting a 'possibly lost' using valgrind client requests with a thread?

Thanks a lot!!
Your assertion kills the program before it's had a chance to destruct t1. The assertion fails because you use VALGRIND_DO_ADDED_LEAK_CHECK at a point where the thread hasn't been destructed yet, so its internal structures are still allocated.
Try this instead:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void proxy_main(){
    std::thread t1(func);
    t1.join();
}

int main()
{
    unsigned int initialErrors_, finalErrors_;
    VALGRIND_DO_ADDED_LEAK_CHECK;
    initialErrors_ = VALGRIND_COUNT_ERRORS;

    proxy_main();

    VALGRIND_DO_ADDED_LEAK_CHECK;
    finalErrors_ = VALGRIND_COUNT_ERRORS;

    assert(initialErrors_ == finalErrors_);

    return 0;
}
Hi helios!

Thanks for your answer, but I tried your code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

#include <cassert>
#include <thread>
#include <valgrind/memcheck.h>

void func(){}

void proxy_main(){
    std::thread t1(func);
    t1.join();
}

int main()
{
    unsigned int initialErrors_, finalErrors_;
    VALGRIND_DO_ADDED_LEAK_CHECK;
    initialErrors_ = VALGRIND_COUNT_ERRORS;

    proxy_main();

    VALGRIND_DO_ADDED_LEAK_CHECK;
    finalErrors_ = VALGRIND_COUNT_ERRORS;

    assert(initialErrors_ == finalErrors_);

    return 0;
}


And I still get the same error :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
288 (+288) bytes in 1 (+1) blocks are possibly lost in loss record 1 of 2
    at 0x4C2FB55: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    by 0x40138A4: allocate_dtv (dl-tls.c:322)
    by 0x40138A4: _dl_allocate_tls (dl-tls.c:539)
    by 0x53DA26E: allocate_stack (allocatestack.c:588)
    by 0x53DA26E: pthread_create@@GLIBC_2.2.5 (pthread_create.c:539)
    by 0x4EF2DC2: std::thread::_M_start_thread(std::shared_ptr<std::thread::_Impl_base>, void (*)()) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
    by 0x4014F3: std::thread::thread<void (&)()>(void (&)()) (thread:137)
    by 0x400FB9: proxy_main() (main.cpp:8)
    by 0x401110: main (main.cpp:18)
 
 LEAK SUMMARY:
    definitely lost: 0 (+0) bytes in 0 (+0) blocks
    indirectly lost: 0 (+0) bytes in 0 (+0) blocks
      possibly lost: 288 (+288) bytes in 1 (+1) blocks
    still reachable: 72,704 (+0) bytes in 1 (+0) blocks
         suppressed: 0 (+0) bytes in 0 (+0) blocks


Thanks anyway
Well, I wrote a nice long explanation, but it's gone now.

Basically, the pointer returned by calloc() is is offset by one block so that pointer arithmetic is required to get the result back. This is enough to confuse Valgrind, resulting in the "possibly lost" message. The structure in question (i.e., the dynamic thread vector) is managed by the runtime and gets freed later. It is not freed immediately because the structure can potentially be re-used.

This is why the final leak summary - which you didn't show - should report all memory was freed. You can write a suppression rule to silence the message if you want.
Last edited on
Hi mbozzi,

Yes you are right, the final message does not show any error at all. I will take a look at how valgrind suppresses errors.

Thanks a lot!
Topic archived. No new replies allowed.