Here's a test program which leaks (on Ubuntu 10.04, ICU 4.2):
#include <unicode/uversion.h>
#include <unicode/calendar.h>
int main()
{
TimeZone* tz = TimeZone::createTimeZone("Asia/Pyongyang");
UErrorCode status = U_ZERO_ERROR;
Calendar* cal = Calendar::createInstance(tz, status); // adopts tz
delete cal;
}
valgrind --leak-check=full says:
==22978== 304 bytes in 1 blocks are possibly lost in loss record 20 of 22
==22978== at 0x4C28F86: malloc (vg_replace_malloc.c:291)
==22978== by 0x526B34D: icu_4_2::UnicodeString::allocate(int) (in /usr/lib/libicuuc.so.42.1)
==22978== by 0x526B993: icu_4_2::UnicodeString::cloneArrayIfNeeded(int, int, signed char, int**, signed char) (in /usr/lib/libicuuc.so.42.1)
==22978== by 0x526D97A: icu_4_2::UnicodeString::doReplace(int, int, unsigned short const*, int, int) (in /usr/lib/libicuuc.so.42.1)
==22978== by 0x4EF0E90: icu_4_2::TimeZone::initDefault() (in /usr/lib/libicui18n.so.42.1)
==22978== by 0x4EF10A4: icu_4_2::TimeZone::createDefault() (in /usr/lib/libicui18n.so.42.1)
==22978== by 0x4EEE750: icu_4_2::GregorianCalendar::GregorianCalendar(icu_4_2::Locale const&, UErrorCode&) (in /usr/lib/libicui18n.so.42.1)
==22978== by 0x4EEB493: ??? (in /usr/lib/libicui18n.so.42.1)
==22978== by 0x4EEBA01: icu_4_2::Calendar::createInstance(icu_4_2::TimeZone*, icu_4_2::Locale const&, UErrorCode&) (in /usr/lib/libicui18n.so.42.1)
==22978== by 0x400A42: icu_4_2::Calendar::createInstance(icu_4_2::TimeZone*, UErrorCode&) (in /home/jzwinck/test/a.out)
==22978== by 0x4009C5: main
My question is, am I using ICU incorrectly, or is there some workaround I can apply to free the default time zone object which ICU seems to be creating? I can't easily change the versions of OS and ICU I'm using.
You need to call u_cleanup() to clean up ICU. Usually it doesn't matter, so is not done automatically. If you build ICU with --enable-auto-cleanup it will attempt to cleanup when the library unloads, on some platforms. See the userguide.
Related
I'm getting a segmentation fault on code that looks perfectly valid to me.
Here's a minimal recreating example:
#include <iostream>
#include <thread>
void func()
{
/* do nothing; thread contents are irrelevant */
}
int main()
{
for (unsigned idx = 0; idx < 1000; idx++)
{
std::thread t(func);
void* buffer = malloc(1000);
free(buffer);
t.join();
}
return 0;
}
I made a run with prints, to check which iteration fails; I got the segmentation fault on iteration #292.
I used gcc-linaro-4.9.4 (taken from here: https://releases.linaro.org/components/toolchain/binaries/4.9-2017.01/arm-linux-gnueabihf/).
I compiled the program this way:
arm-linux-gnueabihf-g++ -std=c++11 -std=gnu++11 -lpthread -pthread main.cpp -o main.out
I tried recreating this in gcc-linaro-6.5, and didn't have the problem there.
Any idea why this happens?
Edit 1
There is no warnings/errors when I compile this code.
Running it under strace reveals nothing special.
Running it under GDB reveals that the segmentation faults happens in free function:
Thread 1 "main.out" received signal SIGSEGV, Segmentation fault.
_int_free (av=0x76d84794 <main_arena>, p=0x1e8bf, have_lock=0) at malloc.c:4043
4043 malloc.c: No such file or directory.
(gdb) bt
#0 _int_free (av=0x76d84794 <main_arena>, p=0x1e8bf, have_lock=0) at malloc.c:4043
#1 0x00010bfa in main ()
Running it under valgrind reveals the following:
==361== Thread 2:
==361== Invalid read of size 4
==361== at 0x4951D64: ??? (in /usr/lib/arm-linux-gnueabihf/libstdc++.so.6.0.22)
==361== Address 0x4becf74 is 0 bytes after a block of size 28 alloc'd
==361== at 0x4847D4C: operator new(unsigned int) (vg_replace_malloc.c:328)
==361== by 0x11629: __gnu_cxx::new_allocator<std::_Sp_counted_ptr_inplace<std::thread::_Impl<std::_Bind_simple<void (*())()> >, std::allocator<std::thread::_Impl<std::_Bind_simple<void (*())()> > >, (__gnu_cxx::_Lock_policy)2> >::allocate(unsigned int, void const*) (in /home/pi/main.out)
==361==
==361== Invalid write of size 4
==361== at 0x4951D6C: ??? (in /usr/lib/arm-linux-gnueabihf/libstdc++.so.6.0.22)
==361== Address 0x4becf74 is 0 bytes after a block of size 28 alloc'd
==361== at 0x4847D4C: operator new(unsigned int) (vg_replace_malloc.c:328)
==361== by 0x11629: __gnu_cxx::new_allocator<std::_Sp_counted_ptr_inplace<std::thread::_Impl<std::_Bind_simple<void (*())()> >, std::allocator<std::thread::_Impl<std::_Bind_simple<void (*())()> > >, (__gnu_cxx::_Lock_policy)2> >::allocate(unsigned int, void const*) (in /home/pi/main.out)
==361==
==361==
==361== HEAP SUMMARY:
==361== in use at exit: 28,000 bytes in 1,000 blocks
==361== total heap usage: 2,002 allocs, 1,002 frees, 1,048,368 bytes allocated
==361==
==361== Thread 1:
==361== 28,000 bytes in 1,000 blocks are definitely lost in loss record 1 of 1
==361== at 0x4847D4C: operator new(unsigned int) (vg_replace_malloc.c:328)
==361== by 0x11629: __gnu_cxx::new_allocator<std::_Sp_counted_ptr_inplace<std::thread::_Impl<std::_Bind_simple<void (*())()> >, std::allocator<std::thread::_Impl<std::_Bind_simple<void (*())()> > >, (__gnu_cxx::_Lock_policy)2> >::allocate(unsigned int, void const*) (in /home/pi/main.out)
==361==
==361== LEAK SUMMARY:
==361== definitely lost: 28,000 bytes in 1,000 blocks
==361== indirectly lost: 0 bytes in 0 blocks
==361== possibly lost: 0 bytes in 0 blocks
==361== still reachable: 0 bytes in 0 blocks
==361== suppressed: 0 bytes in 0 blocks
==361==
==361== For counts of detected and suppressed errors, rerun with: -v
==361== ERROR SUMMARY: 2017 errors from 3 contexts (suppressed: 6 from 3)
edit 2
I still get segmetation fault after I remove the -lpthread and -std=c++11 compilation flags. This is the way I compiled it this time:
arm-linux-gnueabihf-g++ -std=gnu++11 -pthread main.cpp -o main.out
I think the problem is a mismatch between your code and the libstdc++.so library you're linking to.
One possibility is that the wrong libstdc++.so is being used at runtime, which you could check by using the ldd utility. The correct version for GCC 4.9.4 is libstdc++.so.6.0.20 so if you see it linking to a different version, that's a problem.
The second possibility is that it's the right libstdc++.so but it is compiled with different settings from your code, and so the std::thread in your code uses atomic operations for shared_ptr reference counting, but the std::thread in the library uses a mutex (which is the same problem as described in GCC Bug 42734). If the crash and the valgrind errors go away when you compile your program with -march=armv5t then it would confirm this is the problem.
I'm using Valgrind and GDB to debug a memory leak. I've the following call trace that shows where the memory leak occurs:
(gdb) monitor block_list 10104
==961== 153 (18 direct, 135 indirect) bytes in 1 blocks are definitely lost in loss record 10,104 of 10,317
==961== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==961== by 0x678199: create_node(unsigned char const*, unsigned int, document*) (a.cpp:436)
==961== by 0x67933A: insert(art_node*, art_node**, unsigned char const*, unsigned int, document*, unsigned int, int, int*) (a.cpp:704)
==961== by 0x68327B: Program::add(std::string const&) (program.cpp:84)
==961== by 0x7220BF: main (main.cpp:52)
I want to print the value of the string argument that's passed to Program::add at:
==961== by 0x68327B: Program::add(std::string const&) (program.cpp:84)
How do I do that in GDB?
You can follow step by step Valgrind manual:
If you want to debug a program with GDB when using the Memcheck tool,
start Valgrind like this:
valgrind --vgdb=yes --vgdb-error=0 prog
In another shell, start GDB:
gdb prog
Then give the following command to GDB:
(gdb) target remote | vgdb
Now you can go to frame Program::add(std::string const&) in gdb and print the value of argument.
I have a number of unit tests which are run through valgrind.
There are 15 tests in total, all use the same base class (Foo) which has a std::string member (value_) and a virtual destructor.
All unit tests pass, the destructor is called 15 times, but valgrind reports a leak for that string 8 times (for 8 of the 15 tests).
All 8 reported leaks refer to the same string
==30881== 29 bytes in 1 blocks are definitely lost in loss record 8 of 8
==30881== at 0x4A07D73: operator new(unsigned long) (vg_replace_malloc.c:332)
==30881== by 0x3AEF09C3C8: allocate (new_allocator.h:89)
==30881== by 0x3AEF09C3C8: std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) (basic_string.tcc:608)
==30881== by 0x3AEF09DDA9: std::string::_M_mutate(unsigned long, unsigned long, unsigned long) (basic_string.tcc:480)
==30881== by 0x3AEF09DF6B: std::string::_M_replace_safe(unsigned long, unsigned long, char const*, unsigned long) (basic_string.tcc:685)
==30881== by 0xBFB67D: test::TestFoo::TestFoo() (test_foo.h:26)
Line 26 in test_foo.h is where the string is assigned:
TestFoo()
{
value_ = "test"; // line 26
}
I have added the following "check" / "hack" in the Foo destructor (base class of TestFoo):
virtual ~Foo()
{
LOG_TRACE("value capacity(%lu)", value_.capacity());
std::string().swap(value_); // force memory to be released
LOG_TRACE("value capacity(%lu)", value_.capacity());
}
In my log files I verify that the Foo destructor is called 15 times, and for each time, the capacity drops to 0.
|01:13:59.477486350| {TRACE} [Foo::~Foo] value capacity(4)
|01:13:59.479293212| {TRACE} [Foo::~Foo] value capacity(0)
The environment in which this is failing:
CentOS release 6.4 (Final)
g++ (GCC) 5.2.1 20150902 (Red Hat 5.2.1-2)
valgrind-3.11.0
Linux version 2.6.32-696.6.3.el6.x86_64 (mockbuild#c1bl.rdu2.centos.org) (gcc version 4.4.7 20120313 (Red Hat 4.4.7-18) (GCC) ) #1 SMP Wed Jul 12 14:17:22 UTC 2017
Note that on a different machine this failure doesn't happen (Ubuntu 16.04 with gcc 5.4, but the same version of valgrind)
Questions:
Is it possible to fix this so that valgrind doesn't think the memory is leaked, without resorting to a suppression file?
I am running into a range check error from a vector that I am having trouble pin pointing. I am working in a VERY large c++ framework that is not really very well designed. Python is used as a UI which then calls c++ functions/classes to do all the heavy lifting. So the actual command I run is 'python thing.py --option1 etc...'. There is a function that returns an object that it finds by an index in a vector. There are two vectors that it can use based on a bool that is set. To be more concrete, I have something like:
object getObject(int i, bool trig=false){
if(trig) return vector1.at(i);
return vector2.at(i);
}
The problem is that the vectors will be of different lengths so if you either give it the wrong index or you forget to set the 'trig' bool, there is a good chance you will go out of range. This function or something like it is called thousands of times across many different files so I am having trouble finding where this range check error is actually coming from. Currently I have been either commenting out blocks of code, or putting in print outs to try to find where the code gets before it crashes but this is proving quite difficult considering the number of places I have to do this.
Is there an easy way to print out where this function was called from when I get the range check error? Stack trace or something like that? I am not really familiar with things like this.
Update:
I have tried using GDB with a command like:
gdb -ex r --args python fakes.py --datasets data --dir outdir
I see the same error I always get which looks like:
Traceback (most recent call last):
File "fakes.py", line 299, in <module>
main(options,args)
File "fakes.py", line 240, in main
driver.submit(job, submitDir)
Exception: void EL::Driver::submit(const EL::Job& job,
const string& location) =>
DataVector::at range check (C++ exception)
Then it drops me into the GDB command line. If I type bt (which seems to be the right command to get the stack trace) I get the message "No stack."
I tried running Valgrind with this command too but I am not seeing anything useful in it. I could just be missing something however since I am new to valgrind. The following is the output of valgrind around where the error appears:
==344722== Conditional jump or move depends on uninitialised value(s)
==344722== at 0xE80FEC5: TObject::~TObject() (in /cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/root/6.04.12-x86_64-slc6-gcc49-opt/lib/libCore.so)
==344722== by 0x25437C52: EL::Driver::submitOnly(EL::Job const&, std::string const&) const (Driver.cxx:103)
==344722== by 0x25437F88: EL::Driver::submit(EL::Job const&, std::string const&) const (Driver.cxx:84)
==344722== by 0x1CA83031: ???
==344722== by 0xFFE6F7E: TClingCallFunc::exec(void*, void*) const (in /cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/root/6.04.12-x86_64-slc6-gcc49-opt/lib/libCling.so)
==344722== by 0xD1AA1AE: PyROOT::TVoidExecutor::Execute(long, void*, PyROOT::TCallContext*) (in /cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/root/6.04.12-x86_64-slc6-gcc49-opt/lib/libPyROOT.so)
==344722== by 0xD1CB0CB: PyROOT::TMethodHolder::CallSafe(void*, long, PyROOT::TCallContext*) (in /cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/root/6.04.12-x86_64-slc6-gcc49-opt/lib/libPyROOT.so)
==344722== by 0xD1C9DB9: PyROOT::TMethodHolder::Execute(void*, long, PyROOT::TCallContext*) (in /cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/root/6.04.12-x86_64-slc6-gcc49-opt/lib/libPyROOT.so)
==344722== by 0xD1C8A24: PyROOT::TMethodHolder::Call(PyROOT::ObjectProxy*, _object*, _object*, PyROOT::TCallContext*) (in /cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/root/6.04.12-x86_64-slc6-gcc49-opt/lib/libPyROOT.so)
==344722== by 0xD1E35A4: PyROOT::(anonymous namespace)::mp_call(PyROOT::MethodProxy*, _object*, _object*) (in /cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/root/6.04.12-x86_64-slc6-gcc49-opt/lib/libPyROOT.so)
==344722== by 0x4C61B62: PyObject_Call (abstract.c:2529)
==344722== by 0x4D161AD: PyEval_EvalFrameEx (ceval.c:4251)
==344722==
Traceback (most recent call last):
File "fakes.py", line 299, in <module>
main(options,args)
File "fakes.py", line 240, in main
driver.submit(job, submitDir)
Exception: void EL::Driver::submit(const EL::Job& job, const string& location) =>
DataVector::at range check (C++ exception)
==344722== Invalid read of size 4
==344722== at 0x4CB08F3: PyObject_Free (obmalloc.c:994)
==344722== by 0x4D55452: collect (gcmodule.c:821)
==344722== by 0x4D55D27: PyGC_Collect (gcmodule.c:1440)
==344722== by 0x4D3E018: Py_Finalize (pythonrun.c:449)
==344722== by 0x4D53F8E: Py_Main (main.c:665)
==344722== by 0x3038C1ED5C: (below main) (in /lib64/libc-2.12.so)
==344722== Address 0x682d020 is 16 bytes before a block of size 48 alloc'd
==344722== at 0x4A085FC: operator new(unsigned long) (vg_replace_malloc.c:298)
==344722== by 0x10B7DD41: clang::ASTReader::ReadDeclContextStorage(clang::serialization::ModuleFile&, llvm::BitstreamCursor&, std::pair<unsigned long, unsigned long> const&, clang::serialization::DeclContextInfo&) (in /cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/root/6.04.12-x86_64-slc6-gcc49-opt/lib/libCling.so)
==344722== by 0x10BD8CCC: clang::ASTReader::ReadDeclRecord(unsigned int) (in /cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/root/6.04.12-x86_64-slc6-gcc49-opt/lib/libCling.so)
==344722== by 0x10B82DCC: clang::ASTReader::GetDecl(unsigned int) (in /cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/root/6.04.12-x86_64-slc6-gcc49-opt/lib/libCling.so)
==344722== by 0x11036DED: clang::MultiplexExternalSemaSource::GetExternalDecl(unsigned int) (in /cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/root/6.04.12-x86_64-slc6-gcc49-opt/lib/libCling.so)
==344722== by 0x1114F052: clang::ClassTemplateDecl::LoadLazySpecializations() const (in /cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/root/6.04.12-x86_64-slc6-gcc49-opt/lib/libCling.so)
==344722== by 0x1114F078: clang::ClassTemplateDecl::getSpecializations() const (in /cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/root/6.04.12-x86_64-slc6-gcc49-opt/lib/libCling.so)
==344722== by 0x11151209: clang::ClassTemplateDecl::findSpecialization(llvm::ArrayRef<clang::TemplateArgument>, void*&) (in /cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/root/6.04.12-x86_64-slc6-gcc49-opt/lib/libCling.so)
==344722== by 0x10F55800: clang::Sema::CheckTemplateIdType(clang::TemplateName, clang::SourceLocation, clang::TemplateArgumentListInfo&) (in /cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/root/6.04.12-x86_64-slc6-gcc49-opt/lib/libCling.so)
==344722== by 0x10FCC354: clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformTemplateSpecializationType(clang::TypeLocBuilder&, clang::TemplateSpecializationTypeLoc, clang::TemplateName) (in /cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/root/6.04.12-x86_64-slc6-gcc49-opt/lib/libCling.so)
==344722== by 0x10FB8805: clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformType(clang::TypeLocBuilder&, clang::TypeLoc) (in /cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/root/6.04.12-x86_64-slc6-gcc49-opt/lib/libCling.so)
==344722== by 0x10FB8DFC: clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformType(clang::TypeLocBuilder&, clang::TypeLoc) (in /cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/root/6.04.12-x86_64-slc6-gcc49-opt/lib/libCling.so)
this is one of my strangest errors.
QRegularExpression regexp(" .*");
This works fine, sometimes. But than it crashes with segmentation faul.
0 _int_malloc /usr/lib64/libc.so.6 0x7ffff59f2196
1 malloc /usr/lib64/libc.so.6 0x7ffff59f411c
2 operator new(unsigned long) /usr/lib64/libstdc++.so.6 0x7ffff62ac0cd
3 QRegularExpression::QRegularExpression(QString const&, QFlags<QRegularExpression::PatternOption>) /usr/lib64/libQt5Core.so.5 0x7ffff6b45fdd
The Strange thing ist, if i start the program sometimes its okay! No Error at all.
Sometime its crashes after this loc was excecuted excacly 71 times.
I just dont have any clue -.-
EDIT:
char hname[255] ="";
char hname80[255] ="";
char hcas[255] = "";
int i = number;
NAMEdll(i,hname,hname80,hcas);
shortName=hname;
fullName=hname80;
cas=hcas;
// remove unecessary spaces
QRegularExpression regexp(" .*");
cas.remove(regexp);
shortName.remove(regexp);
fullName.remove(regexp)
like suggested i removed code to find the error.
Its seems to have something to do with NAMEdll ( which is a fortran function). If i take out this command, its all fine. With it i get this:
0 _int_malloc /usr/lib64/libc.so.6 0x7ffff59f2196
1 malloc /usr/lib64/libc.so.6 0x7ffff59f411c
2 QArrayData::allocate(unsigned long, unsigned long, unsigned long, QFlags<QArrayData::AllocationOption>) /usr/lib64/libQt5Core.so.5 0x7ffff6a7c0f6
3 QRegularExpressionMatchPrivate::QRegularExpressionMatchPrivate(QRegularExpression const&, QString const&, QRegularExpression::MatchType, QFlags<QRegularExpression::MatchOption>, int) /usr/lib64/libQt5Core.so.5 0x7ffff6b4617a
4 QRegularExpression::match(QString const&, int, QRegularExpression::MatchType, QFlags<QRegularExpression::MatchOption>) const /usr/lib64/libQt5Core.so.5 0x7ffff6b475e4
5 QRegularExpression::globalMatch(QString const&, int, QRegularExpression::MatchType, QFlags<QRegularExpression::MatchOption>) const /usr/lib64/libQt5Core.so.5 0x7ffff6b47c77
6 QString::replace(QRegularExpression const&, QString const&) /usr/lib64/libQt5Core.so.5 0x7ffff6b1c4a9
7 QString::remove qstring.h 429 0x4852fe
Just guessing, but is there a chance that inside the fortran code (its not my ) something can cause a malloc call to fail ? And if it is so, can someone explain how ?
EDIT:
Solved:
Okay i found it by accident.
In a diffrent part of the program i had the following code:
char href[3] ="";
strcpy(href,"DEF");
This is bad, cause strcpy also writes an end character '\0'. So the written chararray has the length of 4.