I try to debug a problem where Valgrind prints uninitialized value errors when using a boost::make_optional in connection with google mock. I tried to simulate the situation with a test app usign memcmp:
#include <string>
#include <boost/optional.hpp>
#include <stdio.h>
#include <cstring>
void testFunction( boost::optional< int > const cacheKey = boost::make_optional ( true, int() ) )
{
boost::optional< int > const cacheKey2 = boost::make_optional ( true, int() );
if ( memcmp ( &cacheKey, &cacheKey2, sizeof ( cacheKey2 ) ) )
{
printf ( "Equal\n" );
}
}
int main(int ac, char** av)
{
testFunction();
}
g++ -std=c++11 -g -O0 -o optionaltest optionaltest.cpp
valgrind --tool=memcheck --track-origins=yes ./optionaltest
==16255== Memcheck, a memory error detector
==16255== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==16255== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==16255== Command: ./optionaltest
==16255==
==16255== Conditional jump or move depends on uninitialised value(s)
==16255== at 0x4C35D72: __memcmp_sse4_1 (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==16255== by 0x1088F9: testFunction(boost::optional<int>) (optionaltest.cpp:11)
==16255== by 0x108995: main (optionaltest.cpp:20)
==16255== Uninitialised value was created by a stack allocation
==16255== at 0x1088BA: testFunction(boost::optional<int>) (optionaltest.cpp:8)
Is there a way to initialize the optional so that there are no uninitialized bytes inside it?
Regards
Edit: I gave both variables a make_optional now. Same error.
Edit 2: Creating a temporary std::optional, nulling it out with memset, then assigning it the value of the original and keep working with the temporary seems to work. It seems to be uninitialized memory in optional_aligned_storage.hpp. I wonder if there is a more elegant solution though.
Related
What's wrong with this program:
#include <string>
int main()
{
std::wstring s = L"12345";
s.find(L"x");
return 0;
}
If nothing is wrong, why does Valgrind complain:
$ g++ -g main.cpp
$ valgrind ./a.out
==9301== Memcheck, a memory error detector
==9301== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==9301== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==9301== Command: ./a.out
==9301==
==9301== Conditional jump or move depends on uninitialised value(s)
==9301== at 0x54AD3C1: __wmemchr_sse2 (memchr.S:254)
==9301== by 0x4F7667A: std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >::find(wchar_t const*, unsigned long, unsigned long) const (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==9301== by 0x108A28: main (main.cpp:5)
==9301==
==9301==
==9301== HEAP SUMMARY:
==9301== in use at exit: 0 bytes in 0 blocks
==9301== total heap usage: 2 allocs, 2 frees, 72,728 bytes allocated
==9301==
==9301== All heap blocks were freed -- no leaks are possible
==9301==
==9301== For counts of detected and suppressed errors, rerun with: -v
==9301== Use --track-origins=yes to see where uninitialised values come from
==9301== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Note that when I reduce the size of the string by one character:
#include <string>
int main()
{
std::wstring s = L"1234"; // string is shorter by one character
s.find(L"x");
return 0;
}
or when I search for a character that is in the string:
#include <string>
int main()
{
std::wstring s = L"12345";
s.find(L"5"); // '5' is in the string
return 0;
}
or when I use std::string instead of std::wstring:
#include <string>
int main()
{
std::string s = "12345"; // std::string instead of std::wstring
s.find("x");
return 0;
}
then Valgrind does not complain.
My environment:
$ uname -a
Linux dave-VirtualBox 4.15.0-101-generic #102-Ubuntu SMP Mon May 11 10:07:26 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
$ g++ --version
g++ (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0
Copyright (C) 2017 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.
$ valgrind --version
valgrind-3.13.0
Probably a bug on valgrind side. I tested with g++ 10.2 and with valgrind 3.16, it worked without an error.
Not really a bug, but the old Valgrind version probably doesn't know about sse string operations.
As an optimization, str* and mem* functions can do 8 byte reads in the knowledge that memory will always be allocated in 8 byte increments. So this may read beyond the end of the string but it will never read unallocated memory.
I am learning about copy constructor and shallow and deep copy. I was following this video: Copying and Copy Constructors in C++
The following code is copied directly from the video and demonstrates shallow copying... (at 9:30 in the video)
This code is supposed to crash after running because the deconstructor will try to deallocate the same memory twice (first for string and later for string2). The first deletion should work fine but the second one should cause the program to crash as we are trying to delete unallocated memory.
Surprisingly, this doesn't happen in my case. I complied code in my command prompt using g++ copying_and_copy_constructor.cpp and it compiled fine and ran it using a.exe. No errors.
#include<iostream>
#include<cstring>
#include<string>
using std::endl;
using std::cout;
class String
{
private:
char* m_Buffer;
unsigned int m_size;
public:
String(const char* string)
{
m_size = strlen(string);
m_Buffer = new char[m_size+1];
memcpy(m_Buffer,string,m_size);
m_Buffer[m_size] = 0;
}
~String()
{
delete [] m_Buffer;
}
friend std::ostream& operator << (std::ostream& stream, const String& string);
};
std::ostream& operator<<(std::ostream& stream, const String& string)
{
stream<< string.m_Buffer;
return stream;
}
int main()
{
String string = "My string";
String string2 = string;
cout<<string2<<endl;
cout<<string;
return 0;
}
I even tried checking in the debugger. I compiled the code using g++ -g copying_and_copy_constructor.cpp and then gdb a.exe. Here is the output of that:
GNU gdb (GDB) 7.6.1
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "mingw32".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from D:\a.exe...done.
(gdb) start
Temporary breakpoint 1 at 0x401446: file copying_and_copy_constructor.cpp, line 43.
Starting program: D:\a.exe
[New Thread 44892.0x8258]
[New Thread 44892.0x6df8]
[New Thread 44892.0xadd8]
[New Thread 44892.0x9658]
Temporary breakpoint 1, main () at copying_and_copy_constructor.cpp:43
43 String string = "My string";
(gdb) c
Continuing.
My string
My string[Inferior 1 (process 44892) exited normally]
(gdb)
The program is not being run.
(gdb) q
This line confuses me My string[Inferior 1 (process 44892) exited normally]. How is this code is exiting normally?
The person in the video is using VS-Code... How can I get the same error in the command prompt?
Crash as shown in the video:
(I don't have vs code as of now (might install it later))
For me (Fedora 32 x86_64) it does crash:
$ g++ -o q q.C -Wall -g;./q
My string
free(): double free detected in tcache 2
Aborted
But I definitely agree such code may look running fine. This is why there is ASAN:
$ g++ -o q q.C -Wall -g -fsanitize=address;./q
My string
=================================================================
==3388436==ERROR: AddressSanitizer: attempting double-free on 0x602000000010 in thread T0:
#0 0x7fb76f262cd7 in operator delete[](void*) (/lib64/libasan.so.6+0xb2cd7)
#1 0x4016e9 in String::~String() /home/jkratoch/t/q.C:25
#2 0x40144b in main /home/jkratoch/t/q.C:42
#3 0x7fb76ecbc041 in __libc_start_main ../csu/libc-start.c:308
#4 0x40120d in _start (/quad/home/jkratoch/t/q+0x40120d)
0x602000000010 is located 0 bytes inside of 10-byte region [0x602000000010,0x60200000001a)
freed by thread T0 here:
#0 0x7fb76f262cd7 in operator delete[](void*) (/lib64/libasan.so.6+0xb2cd7)
#1 0x4016e9 in String::~String() /home/jkratoch/t/q.C:25
#2 0x40143e in main /home/jkratoch/t/q.C:43
#3 0x7fb76ecbc041 in __libc_start_main ../csu/libc-start.c:308
previously allocated by thread T0 here:
#0 0x7fb76f2621d7 in operator new[](unsigned long) (/lib64/libasan.so.6+0xb21d7)
#1 0x4015d6 in String::String(char const*) /home/jkratoch/t/q.C:18
#2 0x4013a0 in main /home/jkratoch/t/q.C:42
#3 0x7fb76ecbc041 in __libc_start_main ../csu/libc-start.c:308
SUMMARY: AddressSanitizer: double-free (/lib64/libasan.so.6+0xb2cd7) in operator delete[](void*)
==3388436==ABORTING
In the case you do not want or even cannot recompile the program with -fsanitize=address you can use Valgrind (but it is slower and it does not detect everything):
$ g++ -o q q.C -Wall -g;valgrind ./q
==3388447== Memcheck, a memory error detector
==3388447== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==3388447== Using Valgrind-3.16.0 and LibVEX; rerun with -h for copyright info
==3388447== Command: ./q
==3388447==
My string
==3388447== Invalid free() / delete / delete[] / realloc()
==3388447== at 0x483C59C: operator delete[](void*) (vg_replace_malloc.c:649)
==3388447== by 0x40139E: String::~String() (q.C:25)
==3388447== by 0x401277: main (q.C:42)
==3388447== Address 0x4db5c80 is 0 bytes inside a block of size 10 free'd
==3388447== at 0x483C59C: operator delete[](void*) (vg_replace_malloc.c:649)
==3388447== by 0x40139E: String::~String() (q.C:25)
==3388447== by 0x40126B: main (q.C:43)
==3388447== Block was alloc'd at
==3388447== at 0x483B582: operator new[](unsigned long) (vg_replace_malloc.c:431)
==3388447== by 0x401334: String::String(char const*) (q.C:18)
==3388447== by 0x40121B: main (q.C:42)
==3388447==
My string==3388447==
==3388447== HEAP SUMMARY:
==3388447== in use at exit: 0 bytes in 0 blocks
==3388447== total heap usage: 3 allocs, 4 frees, 73,738 bytes allocated
==3388447==
==3388447== All heap blocks were freed -- no leaks are possible
==3388447==
==3388447== For lists of detected and suppressed errors, rerun with: -s
==3388447== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
I am learning c++, and am experimenting with loading a shared lib on linux (.so).
I get a segmentation fault when I run the below code.
When I try to run the console app using valgrind, I get the following:
valgrind ./TestLoadSo --leak-check=full -v
==26828== Memcheck, a memory error detector
==26828== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==26828== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==26828== Command: ./TestLoadSo --leak-check=full -v
==26828==
!!!Hello World!!!
==26828== Jump to the invalid address stated on the next line
==26828== at 0x0: ???
==26828== by 0x53E63F0: (below main) (libc-start.c:291)
==26828== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==26828==
==26828==
==26828== Process terminating with default action of signal 11 (SIGSEGV)
==26828== Bad permissions for mapped region at address 0x0
==26828== at 0x0: ???
==26828== by 0x53E63F0: (below main) (libc-start.c:291)
==26828==
==26828== HEAP SUMMARY:
==26828== in use at exit: 3,126 bytes in 9 blocks
==26828== total heap usage: 13 allocs, 4 frees, 76,998 bytes allocated
==26828==
==26828== LEAK SUMMARY:
==26828== definitely lost: 0 bytes in 0 blocks
==26828== indirectly lost: 0 bytes in 0 blocks
==26828== possibly lost: 0 bytes in 0 blocks
==26828== still reachable: 3,126 bytes in 9 blocks
==26828== suppressed: 0 bytes in 0 blocks
==26828== Rerun with --leak-check=full to see details of leaked memory
==26828==
==26828== For counts of detected and suppressed errors, rerun with: -v
==26828== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
[1] 26828 segmentation fault (core dumped) valgrind ./TestLoadSo --leak-check=full -v
C++ Main class
extern "C" typedef char* (*helloWorld_t)();
int main() {
void* handle = dlopen("./libMyLib.dll.so", RTLD_LAZY);
if (!handle) {
cerr << "Cannot open library: " << dlerror() << '\n';
return 1;
}
helloWorld_t hello = (helloWorld_t)dlsym( handle, "helloWorld" );
const char * tmp = hello();
printf("\n%s",tmp);
return 0;
}
The extern function is:
extern "C++" char* helloWorld() {
char str[25];
strcpy(str, "HelloWorld");
}
If I use extern "C" I get a compilation error:
error: conflicting declaration of ‘char* helloWorld()’ with ‘C’ linkage
extern "C" char* helloWorld() {
Its really not clear to me where I am going wrong.
A function cannot have both C and C++ linkage, and a function pointer type must match its target function's linkage.
You cannot dlsym an extern "C++" function by its unadorned name. You have to either use extern "C" in both cases (recommended), or use extern "C++" throughout and replace the string in dlsym(handle, "helloWorld") with the mangled name of your function (not recommended).
Always check the result of dlsym and report an error if it returns a null pointer (use dlerror() like you've done for dlopen).
Don't use character arrays or pointers to represent strings. There is a type for string, called std::string.
Last but not least, always compile with -Wall -Werror so things like a non-void function that doesn't actually return a value will be caught.
Many problems here:
extern "C++" char* helloWorld() {
char str[25];
strcpy(str, "HelloWorld");
}
It should use "C" linkage. And it should return something. And it copies the string to local variable, so value gets lost when it returns. So probably
extern "C" char* helloWorld() {
static char str[25]; // will keep its value accross calls, not thread safe
return strcpy(str, "HelloWorld"); // return pointer to start of str
}
Note that multiple calls all return same static buffer. If you need copies, you need to let caller provide a buffer, or return buffer allocated with malloc.
int main()
{
char *p;
p = malloc(10);
delete(p);
return;
}
what will be appropriate error detected by Valgrind?
First of all this code snippet gives two compilation errors,
In function ‘int main()’:
error: invalid conversion from ‘void*’ to ‘char*’ [-fpermissive]
p = malloc(10);
^
error: return-statement with no value, in function returning ‘int’ [- fpermissive]
return;
Correct the code with these changes,
Type cast while allocating memory using malloc, as shown here.
p = (char*) malloc(10);
The return type of main function is int, so change the return value accordingly, as mentioned here.
return 0; // Use return 0, instead of just return.
Before using delete operation, do a validity check on the pointer, as shown here.
if(p)
delete(p);
With the above changes, and upon successful compilation of the above code. Use the valgrind tool to run the above sample.
As such there is no issue in the code, so valgrind did not find any issue. Below is sample valgrind output.
Valgrind output:
==30050== Memcheck, a memory error detector
==30050== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==30050== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==30050== Command: ./valgrindtest
==30050==
main Start
==30050== Mismatched free() / delete / delete []
==30050== at 0x4C2C18D: operator delete(void*) (vg_replace_malloc.c:576)
==30050== by 0x4006E0: main (valgrindtest.cpp:16)
==30050== Address 0x5a1b040 is 0 bytes inside a block of size 10 alloc'd
==30050== at 0x4C2ABE3: malloc (vg_replace_malloc.c:299)
==30050== by 0x4006C2: main (valgrindtest.cpp:11)
==30050==
main End
==30050==
==30050== HEAP SUMMARY:
==30050== in use at exit: 0 bytes in 0 blocks
==30050== total heap usage: 1 allocs, 1 frees, 10 bytes allocated
==30050==
==30050== All heap blocks were freed -- no leaks are possible
==30050==
==30050== For counts of detected and suppressed errors, rerun with: -v
==30050== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
When I began to learn valgrind(helgrind) tool, I came across such a teedy issue that I failed to tackle.
In simple, a user-defined thread-class is created with a virtual function which would be called by thread's entry routine. If this is the case, helgrind will report Possible-data-race. But after simply omitting virtual keyword, no such errors would ever be reported.
How come this happens this way? Anything wrong with my code? Or is there a workaround?
Hereafter is the simple threaded application demonstrating such issue, including cpp,Makefile and messages that helgrind reports.
/* main.cpp */
#include <memory.h>
#include <pthread.h>
class thread_s {
public:
pthread_t th;
thread_s(void);
~thread_s(void);
virtual void* routine(); /* if omit virtual, no error would be generated */
void stop(void);
};
static void* routine(void*);
int main(int, const char*[])
{
thread_s s_v;
pthread_create(&s_v.th, 0, routine, &s_v);
return 0;
}
static void* routine(void* arg)
{
thread_s *pV = reinterpret_cast<thread_s*>(arg);
pV->routine();
return 0;
}
void* thread_s::routine(void)
{
return 0;
}
thread_s::thread_s(void)
{
th = 0;
}
thread_s::~thread_s(void)
{
stop();
}
void thread_s::stop(void)
{
void *v = 0;
pthread_join(th, &v);
}
=======================================
/* Makefile */
all: main test_helgrind
main: main.cpp
g++ -o main main.cpp \
-g -Wall -O0 \
-lpthread
test_helgrind:
valgrind \
--tool=helgrind \
./main
clean:
rm -f main
.PHONY: clean
=======================================
g++ -o main main.cpp \
-g -Wall -O0 \
-lpthread
valgrind \
--tool=helgrind \
./main
==7477== Helgrind, a thread error detector
==7477== Copyright (C) 2007-2010, and GNU GPL'd, by OpenWorks LLP et al.
==7477== Using Valgrind-3.6.1 and LibVEX; rerun with -h for copyright info
==7477== Command: ./main
==7477==
==7477== Thread #1 is the program's root thread
==7477==
==7477== Thread #2 was created
==7477== at 0x4259728: clone (clone.S:111)
==7477== by 0x40484B5: pthread_create##GLIBC_2.1 (createthread.c:256)
==7477== by 0x4026E2D: pthread_create_WRK (hg_intercepts.c:257)
==7477== by 0x4026F8B: pthread_create#* (hg_intercepts.c:288)
==7477== by 0x8048560: main (main.cpp:18)
==7477==
==7477== Possible data race during write of size 4 at 0xbeab24c8 by thread #1
==7477== at 0x80485C9: thread_s::~thread_s() (main.cpp:35)
==7477== by 0x8048571: main (main.cpp:17)
==7477== This conflicts with a previous read of size 4 by thread #2
==7477== at 0x804858B: routine(void*) (main.cpp:24)
==7477== by 0x4026F60: mythread_wrapper (hg_intercepts.c:221)
==7477== by 0x4047E98: start_thread (pthread_create.c:304)
==7477== by 0x425973D: clone (clone.S:130)
==7477==
==7477==
==7477== For counts of detected and suppressed errors, rerun with: -v
==7477== Use --history-level=approx or =none to gain increased speed, at
==7477== the cost of reduced accuracy of conflicting-access information
==7477== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 1 from 1)
I don't know if this is the reason for helgrind's complaint, but you have a serious problem in you program. You create a thread, passing a pointer to a local thread_s instance (s_v in main()).
However, main() will soon return without any kind of synchronization with thread - there's nothing to ensure that s_v is still alive when the thread function routine() gets hold of the pointer and uses it to call pV->routine().
See if adding the following after the pthread_create() call prevents helgrind from complaining:
pthread_join( s_v.th, NULL);
Actually, looking more closely at the helgrind output, this will almost certainly remove helgrind's complaint, since the log is pointing to the thread_s destructor as one participant in the data race.
In one case the vptr is written, in the other it is read. Both without any lock being held. Helgrind can not know if there are other means in your program that make this condition impossible to happen in two threads simultaneously, so it flags it. If you can guarantee that the object is not destroyed while in another thread someone tries to call a function on it, then you can generate a suppression for this.