वेलग्रिंड लीक ब्लॉक रिपोर्ट कर रहा है, जाहिरा तौर पर धागा प्रति एक, निम्नलिखित कोड में:थ्रेड_लोकल का उपयोग करते समय जीसीसी 4.8.1 में मेमोरी लीक?
#include <iostream>
#include <thread>
#include <mutex>
#include <list>
#include <chrono>
std::mutex cout_mutex;
struct Foo
{
Foo()
{
std::lock_guard<std::mutex> lock(cout_mutex);
std::cout << __PRETTY_FUNCTION__ << '\n';
}
~Foo()
{
std::lock_guard<std::mutex> lock(cout_mutex);
std::cout << __PRETTY_FUNCTION__ << '\n';
}
void
hello_world()
{
std::lock_guard<std::mutex> lock(cout_mutex);
std::cout << __PRETTY_FUNCTION__ << '\n';
}
};
void
hello_world_thread()
{
thread_local Foo foo;
// must access, or the thread local variable may not be instantiated
foo.hello_world();
// keep the thread around momentarily
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
int main()
{
for (int i = 0; i < 100; ++i)
{
std::list<std::thread> threads;
for (int j = 0; j < 10; ++j)
{
std::thread thread(hello_world_thread);
threads.push_back(std::move(thread));
}
while (! threads.empty())
{
threads.front().join();
threads.pop_front();
}
}
}
संकलक संस्करण:
$ g++ --version
g++ (GCC) 4.8.1
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
जीसीसी का निर्माण विकल्प:
--enable-shared
--enable-threads=posix
--enable-__cxa_atexit
--enable-clocale=gnu
--enable-cxx-flags='-fno-omit-frame-pointer -g3'
--enable-languages=c,c++
--enable-libstdcxx-time=rt
--enable-checking=release
--enable-build-with-cxx
--disable-werror
--disable-multilib
--disable-bootstrap
--with-system-zlib
कार्यक्रम संकलन विकल्प:
g++ -std=gnu++11 -Og -g3 -Wall -Wextra -fno-omit-frame-pointer thread_local.cc
valgrind संस्करण:
$ valgrind --version
valgrind-3.8.1
वेलग्रिंड विकल्प: valgrind उत्पादन का
valgrind --leak-check=full --verbose ./a.out > /dev/null
पूंछ अंत:
==1786== HEAP SUMMARY:
==1786== in use at exit: 24,000 bytes in 1,000 blocks
==1786== total heap usage: 3,604 allocs, 2,604 frees, 287,616 bytes allocated
==1786==
==1786== Searching for pointers to 1,000 not-freed blocks
==1786== Checked 215,720 bytes
==1786==
==1786== 24,000 bytes in 1,000 blocks are definitely lost in loss record 1 of 1
==1786== at 0x4C29969: operator new(unsigned long, std::nothrow_t const&) (vg_replace_malloc.c:329)
==1786== by 0x4E8E53E: __cxa_thread_atexit (atexit_thread.cc:119)
==1786== by 0x401036: hello_world_thread() (thread_local.cc:34)
==1786== by 0x401416: std::thread::_Impl<std::_Bind_simple<void (*())()> >::_M_run() (functional:1732)
==1786== by 0x4EE4830: execute_native_thread_routine (thread.cc:84)
==1786== by 0x5A10E99: start_thread (pthread_create.c:308)
==1786== by 0x573DCCC: clone (clone.S:112)
==1786==
==1786== LEAK SUMMARY:
==1786== definitely lost: 24,000 bytes in 1,000 blocks
==1786== indirectly lost: 0 bytes in 0 blocks
==1786== possibly lost: 0 bytes in 0 blocks
==1786== still reachable: 0 bytes in 0 blocks
==1786== suppressed: 0 bytes in 0 blocks
==1786==
==1786== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 2 from 2)
--1786--
--1786-- used_suppression: 2 dl-hack3-cond-1
==1786==
==1786== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 2 from 2)
निर्माणकर्ता और विनाशकर्ता प्रत्येक थ्रेड के लिए एक बार चलाने गया:
$ ./a.out | grep 'Foo::Foo' | wc -l
1000
$ ./a.out | grep hello_world | wc -l
1000
$ ./a.out | grep 'Foo::~Foo' | wc -l
1000
नोट्स:
- आपके द्वारा बनाए गए थ्रेड की संख्या बदलते हैं, तो लीक ब्लॉक की संख्या थ्रेड की संख्या से मेल खाता है।
- कोड इस तरह से संरचित किया गया है कि परमिट संसाधन पुन: उपयोग (यानी लीक ब्लॉक) अगर जीसीसी लागू किया गया हो। एक कार्यक्रम चलाने के बारे में 10 सेकंड का समय लगता है, sleep_for() कॉल के कारण
thread_local Foo foo;
- :
- valgrind स्टैकट्रेस से, thread_local.cc:34 रेखा है।
कोई विचार अगर यह स्मृति रिसाव जीसीसी में है, तो मेरे कॉन्फ़िगरेशन विकल्पों का परिणाम है, या मेरे प्रोग्राम में कुछ बग है?
यह एक पूरी तरह से तैयार प्रश्न का एक चमकदार उदाहरण है, अच्छी तरह से किया गया। – GManNickG
आप 'स्थिर 'का उपयोग क्यों करते हैं? – stefan
फिक्स्ड। मैं valgrind फिर से भाग गया, लेकिन दुर्भाग्य से रिसाव अभी भी मौजूद है। – user2224952