Closed artiomn closed 4 months ago
In your code I don't see that any instance of CpuPower/SystemCounterState was ever created.
==2902827== by 0x91FBAE: __static_initialization_and_destruction_0() (utils.cpp:139)
This allocation is here: https://github.com/intel/pcm/blob/38aaf6c730345df195430bc0082a16787da2caf2/src/utils.cpp#L139 Not really related to SystemCounterState
Could be a valgrind issue?
Yes. Because even an object of this class has not been created. But the problem only happened when I linked the PCM to the library (and in my library even memory is not allocated or freed explicitly, and nothing called from it (temporarily commented)).
I tried to uncomment other attributes and comment sstates
. And sometimes it repeats.
Probably this is happening in some PCM finalization code that is called when the library is unloaded?
Could be a valgrind issue?
Definitely not, because I see double free without Valgrind.
Stack:
Thread 1 (Thread 0x7fc8ea43a500 (LWP 3645867) "knp-tester"):
#0 0x00007fc8ea590e44 in ?? () from /usr/lib/libc.so.6
No symbol table info available.
#1 0x00007fc8ea538a30 in raise () from /usr/lib/libc.so.6
No symbol table info available.
#2 0x00007fc8ea5204c3 in abort () from /usr/lib/libc.so.6
No symbol table info available.
#3 0x00007fc8ea521354 in ?? () from /usr/lib/libc.so.6
No symbol table info available.
#4 0x00007fc8ea59b085 in ?? () from /usr/lib/libc.so.6
No symbol table info available.
#5 0x00007fc8ea59d66f in ?? () from /usr/lib/libc.so.6
No symbol table info available.
#6 0x00007fc8ea59fdae in free () from /usr/lib/libc.so.6
No symbol table info available.
#7 0x000055bfe327d426 in std::__new_allocator<char const*>::deallocate (this=0x55bfe34c8a40 <pcm::colorTable>, __p=0x55bfe4e026d0, __n=10) at /usr/include/c++/14.1.1/bits/new_allocator.h:172
No locals.
#8 0x000055bfe327aa10 in std::allocator_traits<std::allocator<char const*> >::deallocate (__a=..., __p=0x55bfe4e026d0, __n=10) at /usr/include/c++/14.1.1/bits/alloc_traits.h:513
No locals.
#9 std::_Vector_base<char const*, std::allocator<char const*> >::_M_deallocate (this=0x55bfe34c8a40 <pcm::colorTable>, __p=0x55bfe4e026d0, __n=10) at /usr/include/c++/14.1.1/bits/stl_vector.h:389
No locals.
#10 0x000055bfe327951c in std::_Vector_base<char const*, std::allocator<char const*> >::~_Vector_base (this=0x55bfe34c8a40 <pcm::colorTable>, __in_chrg=<optimized out>) at /usr/include/c++/14.1.1/bits/stl_vector.h:368
No locals.
#11 0x000055bfe32781fb in std::vector<char const*, std::allocator<char const*> >::~vector (this=0x55bfe34c8a40 <pcm::colorTable>, __in_chrg=<optimized out>) at /usr/include/c++/14.1.1/bits/stl_vector.h:738
No locals.
#12 0x00007fc8ea53aa60 in __cxa_finalize () from /usr/lib/libc.so.6
No symbol table info available.
#13 0x00007fc8ea258298 in ?? () from /home/artiom/projects/KNP/build/linux-default/bin/libknp-devices-cpu.so.1
No symbol table info available.
#14 0x00007ffeb32dc540 in ?? ()
No symbol table info available.
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
Compiler: gcc-14.1.1, C++17.
Aha, got it!
utils.cpp:128:
std::vector<const char *> colorTable = {
ASCII_GREEN,
ASCII_YELLOW,
ASCII_MAGENTA,
ASCII_CYAN,
ASCII_BRIGHT_GREEN,
ASCII_BRIGHT_YELLOW,
ASCII_BRIGHT_BLUE,
ASCII_BRIGHT_MAGENTA,
ASCII_BRIGHT_CYAN,
ASCII_BRIGHT_WHITE
};
Problem happened, when the vector destructor called. Probably destructor trying to delete constexpr global string by the pointer. But that's just a guess.
It can be fixed by replacing vector with array:
constexpr static std::array<const char *, 10> colorTable = {
ASCII_GREEN,
ASCII_YELLOW,
ASCII_MAGENTA,
ASCII_CYAN,
ASCII_BRIGHT_GREEN,
ASCII_BRIGHT_YELLOW,
ASCII_BRIGHT_BLUE,
ASCII_BRIGHT_MAGENTA,
ASCII_BRIGHT_CYAN,
ASCII_BRIGHT_WHITE
};
thanks for the valgrind W/A.
Definitely not, because I see double free without Valgrind.
Unfortunately I still don't see why colorTable destructor needs to be called twice by __run_exit_handlers. What is wrong in having static std::vector arrays?
thanks for the valgrind W/A.
Definitely not, because I see double free without Valgrind.
Unfortunately I still don't see why colorTable destructor needs to be called twice by __run_exit_handlers. What is wrong in having static std::vector arrays?
See above.
Probably vector destructor trying to remove constexpr string by the pointer (delete ASCII_GREEN;
).
There are no errors with std::array
.
I thought ASCII_GREEN itself is not allocated on the heap. It is a constexpr already
constexpr const char* ASCII_GREEN = "\033[0;32m";
And no delete should be called for it. Only for the std vector array that holds the pointers to those constexpr char *. Assuming delete is called when they are in std::vector why it is not called when these pointers are stored in a different container "std::array" instead of "std::vector"?
Does it also report a leak if you put a vector with a different type (int instead of char *):
std::vector
I thought ASCII_GREEN itself is not allocated on the heap. It is a constexpr already
Yes.
And no delete should be called for it. Only for the std vector array that holds the pointers to those constexpr char *.
Yes.
why it is not called when these pointers are stored in a different container "std::array" instead of "std::vector"?
Because this container is constexpr, but the vector is not and frees memory (from .rodata?) in runtime.
Does it also report a leak if you put a vector with a different type (int instead of char *):
This is not a leak, this is a double free: deallocating already deallocated memory. And no, in this case problem doesn't exists (I haven't checked, but I think not).
Strictly speaking, a vector does not free memory. This is done by an allocator, the class of which is passed as a template parameter. IMHO, allocator for the char* is different, but I'm not sure: I don't remember and really don't have time to investigate it.
As a fact: with constexpr array the double free problem was gone.
thanks.. I meant double-free, not a leak. As a developer one can expect that if one writes something like that: std::vector<const char *> arrayOfStrings = {"AA","BB"}; this won't result in double-free :-) Thanks for spending time in debugging this.
Anyway, if you have more time a pull request would be welcome.
With vector probably my explanation is not correct. But problem is definitely exists.
My idea was that the line is deleted in runtime, and then automatically when the application is unloaded.
This did not happen with std::array
, not because it is a different container, but because it is a constexpr container (if you can make constexpr vector in C++17, I think it will be good too).
Yes, probably, you're right. Strings will not be deleted by the pointer. It's my failure.
But double-free exists somewhere here.
I have a class to get power, consuming by core:
All code in methods are commented, all attributes, except
sstates
are commented. This class is a part of the library, statically linked to the bare gtest tester. Tester code:Running tester gives double free:
After commenting sstates (even if other attributes are uncommented), all works:
This error exists only on Linux, not on Windows.
Valgrind output:
This problem doesn't exist in PCM 202403.