std::wstring::find() broken in g++? - c++

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.

Related

Uninitialized value error with valgrind and boost::optional

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.

Why isn't this program crashing? (shallow copy)

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)

Load shared lib in c++ causes segmentation fault

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.

Valgrind tool for GDB

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)

llvm-gcc std::allocator bug?

The code:
#include <vector>
#include <stack>
using namespace std;
class blub {};
class intvec : public std::vector<int, std::allocator<int> >, public blub {};
int main()
{
std::stack<int, intvec> s;
}
compiles with both g++ (4.4.3) and llvm-g++ (4.2.1), but the output of the latter seg faults:
$ g++ main.cc && ./a.out
$ llvm-g++ main.cc && ./a.out
Segmentation fault
It appears to be an issue of freeing something that wasn't allocated. Is this a bug in llvm-gcc?
Update: Based on the discuss on the llvm mailing list, it looks like this is a bug, either in llvm-gcc or its implementation of the STL that has been fixed in newer versions. I haven't bother to install and build llvm-gcc from their repository to find out, however.
Okay. So I ran this on Ubuntu 10.10 x64 and I see the segmentation fault. Here's some details. In general, my summary seems to be that this is a bug in the compiler. (Note that I'm not the original question asker, I was merely able to reproduce his results).
I've also forwarded this to the llvm mailing list at http://lists.cs.uiuc.edu/pipermail/llvmdev/2010-November/036231.html
wlynch#green:/tmp$ llvm-g++ --version
llvm-g++ (GCC) 4.2.1 (Based on Apple Inc. build 5658) (LLVM build)
Copyright (C) 2007 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.
wlynch#green:/tmp$ llvm-g++ -O0 -g main.cc && ./a.out
Segmentation fault
wlynch#green:/tmp$ llvm-g++ -O3 -g main.cc && ./a.out
Segmentation fault
(gdb) bt
#0 0x00007ffff780aa75 in *__GI_raise (sig=<value optimized out>) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
#1 0x00007ffff780e5c0 in *__GI_abort () at abort.c:92
#2 0x00007ffff78444fb in __libc_message (do_abort=<value optimized out>, fmt=<value optimized out>) at ../sysdeps/unix/sysv/linux/libc_fatal.c:189
#3 0x00007ffff784e5b6 in malloc_printerr (action=3, str=0x7ffff791ead3 "free(): invalid pointer", ptr=<value optimized out>) at malloc.c:6266
#4 0x00007ffff7854e83 in *__GI___libc_free (mem=<value optimized out>) at malloc.c:3738
#5 0x0000000000401476 in __gnu_cxx::new_allocator<int>::deallocate (this=0x7fffffffe5a8, __p=0x62c000, unnamed_arg=4) at include/c++/4.2.1/ext/new_allocator.h:97
#6 0x00000000004014b1 in std::_Vector_base<int, std::allocator<int> >::_M_deallocate (this=0x7fffffffe5a8, __p=0x62c000, __n=4) at include/c++/4.2.1/bits/stl_vector.h:146
#7 0x00000000004014fe in std::_Vector_base<int, std::allocator<int> >::~_Vector_base (this=0x7fffffffe5a8) at include/c++/4.2.1/bits/stl_vector.h:132
#8 0x00000000004017cf in std::vector<int, std::allocator<int> >::~vector (this=0x7fffffffe5a8) at include/c++/4.2.1/bits/stl_vector.h:287
#9 0x0000000000401886 in intvec::~intvec (this=0x7fffffffe5a8) at main.cc:6
#10 0x00000000004018a4 in std::stack<int, intvec>::~stack (this=0x7fffffffe5a8) at include/c++/4.2.1/bits/stl_stack.h:99
#11 0x0000000000400c01 in main () at main.cc:10
We also get a free of an invalid pointer. Which makes sense from the traceback.
wlynch#green:/tmp$ valgrind ./a.out
==4644== Memcheck, a memory error detector
==4644== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==4644== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
==4644== Command: ./a.out
==4644==
==4644== Invalid free() / delete / delete[]
==4644== at 0x4C270BD: free (vg_replace_malloc.c:366)
==4644== by 0x401475: __gnu_cxx::new_allocator<int>::deallocate(int*, unsigned long) (new_allocator.h:97)
==4644== by 0x4014B0: std::_Vector_base<int, std::allocator<int> >::_M_deallocate(int*, unsigned long) (stl_vector.h:146)
==4644== by 0x4014FD: std::_Vector_base<int, std::allocator<int> >::~_Vector_base() (stl_vector.h:132)
==4644== by 0x4017CE: std::vector<int, std::allocator<int> >::~vector() (stl_vector.h:287)
==4644== by 0x401885: intvec::~intvec() (main.cc:6)
==4644== by 0x4018A3: std::stack<int, intvec>::~stack() (stl_stack.h:99)
==4644== by 0x400C00: main (main.cc:10)
==4644== Address 0x5433000 is not stack'd, malloc'd or (recently) free'd
==4644==
==4644==
==4644== HEAP SUMMARY:
==4644== in use at exit: 1 bytes in 1 blocks
==4644== total heap usage: 1 allocs, 1 frees, 1 bytes allocated
==4644==
==4644== LEAK SUMMARY:
==4644== definitely lost: 1 bytes in 1 blocks
==4644== indirectly lost: 0 bytes in 0 blocks
==4644== possibly lost: 0 bytes in 0 blocks
==4644== still reachable: 0 bytes in 0 blocks
==4644== suppressed: 0 bytes in 0 blocks
==4644== Rerun with --leak-check=full to see details of leaked memory
==4644==
==4644== For counts of detected and suppressed errors, rerun with: -v
==4644== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4)
I reduced the test case a bit. I'm actually leaning towards this being a STL implementation error, rather than a compiler error.
#include <vector>
class blub {};
class intvec : public std::vector<int>, public blub {};
int main() {
intvec d;
intvec e(d);
}
To figure out what's actually happening, try to compile with the -g flag to enable debug information to be emitted, then run valgrind ./a.out to get a stack trace where the segfault occurs.
does not segfault for me, what platform are you using?
macmini:stackoverflow samm$ llvm-g++ --version
llvm-g++ (GCC) 4.2.1 (Based on Apple Inc. build 5658) (LLVM build)
Copyright (C) 2007 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.
macmini:stackoverflow samm$ cat stack.cc
#include <vector>
#include <stack>
using namespace std;
class blub {};
class intvec : public std::vector<int, std::allocator<int> >, public blub {};
int main()
{
std::stack<int, intvec> s;
}
macmini:stackoverflow samm$ llvm-g++ -g stack.cc
macmini:stackoverflow samm$ ./a.out
macmini:stackoverflow samm$ echo $?
0
macmini:stackoverflow samm$