Hi everyone, im trying to complete a code involving my own exception but im having a few errors while running valgrind.
the errors dont happen all the time, usually only the first time tried. it seems as though the string of the exception is giving trouble but it still prints it when the exception is thrown...any ideas what might be causing the problems?
thx for your time :)
#include <iostream>
#include <sstream>
#include <exception>
using namespace std;
class wrongMessageIndex:public exception{
public:
int index;
public:
wrongMessageIndex(int& num){index=num;};
virtual const char* what() const throw(){
stringstream s;
string k="Wrong message index: ";
s<<k<<index;
return (s.str().c_str());
}
};
class NoUserInSystem:public exception{
public:
string user;
public:
NoUserInSystem(string name){user=name;};
virtual const char* what() const throw(){
string k=user;
k+=": no such user ";
return (k.c_str());
}
virtual ~NoUserInSystem() throw(){}
};
class MemoreyFail:public exception{
public:
virtual const char* what() const throw(){
return ("Unable to create new message or write in the right file");
}
virtual ~MemoreyFail() throw(){}
};
the part from which the exception is thrown
string user="";
int checker=0;
while(!file.eof()){
getline(file,user);
if(strcmp(user.c_str(),to_who.c_str())==0)
{
checker=-1;
}
}
if(checker!=-1||strcmp(this->nameOfUser.c_str(),to_who.c_str())==0){
throw NoUserInSystem(to_who);
}
this is where the exception is caught:
try{
this->sendSingleMessage();
}
catch(exception& e){
cout<<e.what()<<endl;
}
here a few of the errors i get
Welcome zamri , you have 2 new messages.
Eva would like to update you that:
What would you like to do?
(1) See the list of all messages
(2) Read the next new message
(3) Read a message by index number
(4) Read a complete correspondence
(5) Write a new message
(6) Write a new mass-message
(7) Quit
Please type you choice
5
To:tony
==2945== Invalid read of size 1
==2945== at 0x402C658: strlen (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==2945== by 0x40CAC2D: std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*) (in /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16)
==2945== by 0x804A144: main (in /home/ise/Ass4/myMs)
==2945== Address 0x4342834 is 12 bytes inside a block of size 32 free'd
==2945== at 0x402ACFC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==2945== by 0x40D699A: std::string::_Rep::_M_destroy(std::allocator<char> const&) (in /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16)
==2945== by 0x804D2A2: RegularUser::showMenue() (in /home/ise/Ass4/myMs)
==2945== by 0x804A144: main (in /home/ise/Ass4/myMs)
==2945==
==2945== Invalid read of size 1
==2945== at 0x402C663: strlen (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==2945== by 0x40CAC2D: std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*) (in /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16)
==2945== by 0x804A144: main (in /home/ise/Ass4/myMs)
==2945== Address 0x4342835 is 13 bytes inside a block of size 32 free'd
==2945== at 0x402ACFC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==2945== by 0x40D699A: std::string::_Rep::_M_destroy(std::allocator<char> const&) (in /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16)
==2945== by 0x804D2A2: RegularUser::showMenue() (in /home/ise/Ass4/myMs)
==2945== by 0x804A144: main (in /home/ise/Ass4/myMs)
==2945==
==2945== Invalid read of size 1
==2945== at 0x41B868B: _IO_file_xsputn##GLIBC_2.1 (fileops.c:1330)
==2945== by 0x41AD757: fwrite (iofwrite.c:45)
==2945== by 0x40C9075: __gnu_cxx::stdio_sync_filebuf<char, std::char_traits<char> >::xsputn(char const*, int) (in /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16)
==2945== by 0x40CA9AA: std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, int) (in /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16)
==2945== by 0x40CAC3D: std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*) (in /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16)
==2945== by 0x804A144: main (in /home/ise/Ass4/myMs)
==2945== Address 0x4342846 is 30 bytes inside a block of size 32 free'd
==2945== at 0x402ACFC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==2945== by 0x40D699A: std::string::_Rep::_M_destroy(std::allocator<char> const&) (in /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16)
==2945== by 0x804D2A2: RegularUser::showMenue() (in /home/ise/Ass4/myMs)
==2945== by 0x804A144: main (in /home/ise/Ass4/myMs)
==2945==
==2945== Invalid read of size 1
==2945== at 0x41B869F: _IO_file_xsputn##GLIBC_2.1 (fileops.c:1330)
==2945== by 0x41AD757: fwrite (iofwrite.c:45)
==2945== by 0x40C9075: __gnu_cxx::stdio_sync_filebuf<char, std::char_traits<char> >::xsputn(char const*, int) (in /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16)
==2945== by 0x40CA9AA: std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, int) (in /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16)
==2945== by 0x40CAC3D: std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*) (in /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16)
==2945== by 0x804A144: main (in /home/ise/Ass4/myMs)
==2945== Address 0x4342845 is 29 bytes inside a block of size 32 free'd
==2945== at 0x402ACFC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==2945== by 0x40D699A: std::string::_Rep::_M_destroy(std::allocator<char> const&) (in /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16)
==2945== by 0x804D2A2: RegularUser::showMenue() (in /home/ise/Ass4/myMs)
==2945== by 0x804A144: main (in /home/ise/Ass4/myMs)
==2945==
return (s.str().c_str());
returns a pointer to the first element of the internal buffer of a temporary copy of the buffer of your stream object. So this pointer is dangling as soon as what() completes.
Basically the same problem:
return (k.c_str());
returns a pointer into the buffer of the local string k which will immediately go out of scope.
To solve this, just drop this pointer business and simply return an std::string by value.
Related
I have a code snippet from the course which is "Learn Multithreading with Modern C++" from udemy. (it is concurent queue demo example)
#include <queue>
#include <mutex>
#include <condition_variable>
#include <iostream>
#include <future>
#include <string>
using namespace std;
template <class T>
class concurrent_queue_cv {
std::mutex m;
std::queue<T> q;
std::condition_variable cv;
public:
concurrent_queue_cv() = default;
void push(T value) {
std::lock_guard<std::mutex> lg(m);
q.push(value);
cv.notify_one();
}
void pop(T& value) {
std::unique_lock<std::mutex> lg(m);
cv.wait(lg, [this] {return !q.empty();});
value = q.front();
q.pop();
}
};
concurrent_queue_cv<string> cq;
// Waiting thread
void reader() {
string sdata;
cout << "Reader calling pop..." << endl;
cq.pop(sdata); // Pop the data off the queue
cout << "Reader received data: " << sdata << endl;
}
// Modyifing thread
void writer() {
std::this_thread::sleep_for(2s); // Pretend to be busy...
cout << "Writer calling push..." << endl;
cq.push("Populated"); // Push the data onto the queue
cout << "Writer returned from push..." << endl;
}
int main() {
cout << "Starting reader" << endl;
auto r = async(std::launch::async, reader);
cout << "Starting writer" << endl;
auto w = async(std::launch::async, writer);
r.wait();
w.wait();
}
When I run this code with helgrind I got these.
==1072==
==1072== Possible data race during write of size 1 at 0x4E03F4E by thread #1
==1072== Locks held: none
==1072== at 0x48488A6: mempcpy (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_helgrind-amd64-linux.so)
==1072== by 0x4B3B661: _IO_new_file_xsputn (fileops.c:1236)
==1072== by 0x4B3B661: _IO_file_xsputn##GLIBC_2.2.5 (fileops.c:1197)
==1072== by 0x4B2F3F0: fwrite (iofwrite.c:39)
==1072== by 0x49E2823: std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long) (in /lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
==1072== by 0x49E2BDB: std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*) (in /lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
==1072== by 0x10BB05: main (in /home/user/concurentQueue)
==1072==
==1072== This conflicts with a previous write of size 1 by thread #2
==1072== Locks held: none
==1072== at 0x48488A6: mempcpy (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_helgrind-amd64-linux.so)
==1072== by 0x4B3B661: _IO_new_file_xsputn (fileops.c:1236)
==1072== by 0x4B3B661: _IO_file_xsputn##GLIBC_2.2.5 (fileops.c:1197)
==1072== by 0x4B2F3F0: fwrite (iofwrite.c:39)
==1072== by 0x49E2823: std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long) (in /lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
==1072== by 0x49E2BDB: std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*) (in /lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
==1072== by 0x10B8CC: reader() (in /home/user/concurentQueue)
==1072== by 0x1131E3: void std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)()) (in /home/user/concurentQueue)
==1072== by 0x113113: std::__invoke_result<void (*)()>::type std::__invoke<void (*)()>(void (*&&)()) (in /home/user/concurentQueue)
==1072== Address 0x4e03f4e is 14 bytes inside a block of size 1,024 alloc'd
==1072== at 0x483C893: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_helgrind-amd64-linux.so)
==1072== by 0x4B2DD33: _IO_file_doallocate (filedoalloc.c:101)
==1072== by 0x4B3DEFF: _IO_doallocbuf (genops.c:347)
==1072== by 0x4B3CF5F: _IO_file_overflow##GLIBC_2.2.5 (fileops.c:745)
==1072== by 0x4B3B6E4: _IO_new_file_xsputn (fileops.c:1244)
==1072== by 0x4B3B6E4: _IO_file_xsputn##GLIBC_2.2.5 (fileops.c:1197)
==1072== by 0x4B2F3F0: fwrite (iofwrite.c:39)
==1072== by 0x49E2823: std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long) (in /lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
==1072== by 0x49E2BDB: std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*) (in /lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
==1072== by 0x10BAC5: main (in /home/user/concurentQueue)
==1072== Block was alloc'd by thread #1
==1072==
--1072--
--1072-- used_suppression: 58 helgrind-glibc2X-004 /usr/lib/x86_64-linux-gnu/valgrind/default.supp:949
--1072-- used_suppression: 12 helgrind-glibc2X-005 /usr/lib/x86_64-linux-gnu/valgrind/default.supp:963
==1072==
==1072== ERROR SUMMARY: 72 errors from 8 contexts (suppressed: 70 from 49)
If I am not wrong, this code snippet may have data race according to helgrind.
but when I compile this with clang using -fsanitize=thread then it does not show any potential data race.
clang++ -fsanitize=thread -g -O1 concurentQueue.cpp -lpthread -o concurentQueue
My question is that can we trust helgrind ? Or does the code snippet have data race ?
The issues are because of the couts. When cout lines are removed then helgrind will not give any negative result.
==3275== Invalid read of size 8
==3275== at 0x53D006E: _IO_file_xsputn##GLIBC_2.2.5 (fileops.c:1362)
==3275== by 0x53C5C6C: fwrite (iofwrite.c:45)
==3275== by 0x4EE4C9D: std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==3275== by 0x4EE4FA6: std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==3275== by 0x401D4C: main (q2.cc:45)
==3275== Address 0x5a254b8 is 24 bytes inside a block of size 43 free'd
==3275== at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3275== by 0x4EF27BF: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==3275== by 0x40197D: read(std::istream&, character&) (utf8char.cc:16)
==3275== by 0x401B6C: main (q2.cc:27)
This is the relevant code:
infile = new ifstream(argv[1]);
character CurrChar;
character &UTF = CurrChar;
where character is a structure that holds 4 bytes. I don't think it's relevant.
q2.cc:27 utfchar = read(*infile, UTF)
q2.cc:44 catch (UTF8err err) {
q2.cc:45 cout << err.msg << ends;
q2.cc:46 ....
where err is :
struct UTF8err { // exception
const char *msg;`
UTF8err( const char *msg ) : msg( msg ) {}
};
utf8char.cc:16 string pad = " : invalid padding";
When you call c_str, the result is valid so long as the string isn't modified or destroyed. But when you throw, the stack is unwound, destroying the string. So the pointer points to something that no longer exists.
Perhaps change the type of msg from const char* to std::string. Perhaps make the string static. Perhaps make the UTF8err class manage its own memory.
I am using "std::stringstream", for converting "long" value to "hex-string", for further usage in code.
Code snippet as below:
void initDisplayVariant(){
...
/// integer value to hex-string
std::stringstream sstream;
sstream << "0x"
<< std::setfill ('0') << std::setw(2)
<< std::hex << (int)frntDispVariant;
std::string frntDispVariantHex = sstream.str();
sstream.clear(); //clears out the stream-string
...
}
But, valgrind lists the location in "reachable-leaks".
...
==6736== 0 bytes in 1 blocks are still reachable in loss record 1 of 143
==6736== at 0x4024045: operator new[](unsigned int) (vg_replace_malloc.c:299)
==6736== by 0x5232570: std::__numpunct_cache<char>::_M_cache(std::locale const&) (in /usr/lib/libstdc++.so.6.0.14)
==6736== by 0x5236684: std::ostreambuf_iterator<char, std::char_traits<char> > std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::_M_insert_int<long>(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, long) const (in /usr/lib/libstdc++.so.6.0.14)
==6736== by 0x523678D: std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::do_put(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, long) const (in /usr/lib/libstdc++.so.6.0.14)
==6736== by 0x5241B43: std::ostream& std::ostream::_M_insert<long>(long) (in /usr/lib/libstdc++.so.6.0.14)
==6736== by 0x5241CB4: std::ostream::operator<<(int) (in /usr/lib/libstdc++.so.6.0.14)
==6736== by 0x808E76B: initDisplayVariant() (src.cpp:45)
...
Since the stream is local to method and should not exist beyond the method's scope (even though it does alloc internally), so the context of reported-leak is not clear.
Any clue or suggestion?
I have following code:
Document document;
char *buf = new char[str.size()+1];
buf[str.size()] = '\0';
memcpy(buf, str.c_str(), str.size());
//string parsing
if (document.ParseInsitu<0>(buf).HasParseError()) {
cerr << "Failed to parse string ";
}
delete[] buf;
When I check the program with valgrind I get this:
==29765== Invalid read of size 1
==29765== at 0x402A682: bcmp (mc_replace_strmem.c:679)
==29765== Address 0x49626a2 is 2 bytes inside a block of size 214 free'd
==29765== at 0x402759B: operator delete[](void*) (vg_replace_malloc.c:409)
==29765== Invalid read of size 1
==29765== at 0x402901A: strlen (mc_replace_strmem.c:282)
==29765== by 0x41ABE4A: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&) (in /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16)
==29765== Address 0x49626a8 is 8 bytes inside a block of size 214 free'd
==29765== at 0x402759B: operator delete[](void*) (vg_replace_malloc.c:409)
==29765== Invalid read of size 1
==29765== at 0x4029D0E: memcpy (mc_replace_strmem.c:635)
==29765== by 0x41ABD15: char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&, std::forward_iterator_tag) (in /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16)
==29765== by 0x41ABE65: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&) (in /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16)
==29765== by 0x2C23: ???
==29765== Address 0x49626b2 is 18 bytes inside a block of size 214 free'd
==29765== at 0x402759B: operator delete[](void*) (vg_replace_malloc.c:409)
what am I doing wrong?
buf[json.size()] = '\0';
isn't this supposed to be:
buf[str.size()] = '\0';
?
The problem was that I was deallocating buf too early. I supposed that the parser will make a copy of the input, which was obviously wrong.
I have the following error when using valgrind:
==3099== Conditional jump or move depends on uninitialised value(s)
==3099== at 0x40BA65D: std::ostreambuf_iterator<char, std::char_traits<char> > std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::_M_insert_int<long>(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, long) const (in /usr/lib/libstdc++.so.6.0.14)
==3099== by 0x40BA98C: std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::do_put(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, long) const (in /usr/lib/libstdc++.so.6.0.14)
==3099== by 0x40C5A98: std::ostream& std::ostream::_M_insert<long>(long) (in /usr/lib/libstdc++.so.6.0.14)
==3099== by 0x40C5C13: std::ostream::operator<<(int) (in /usr/lib/libstdc++.so.6.0.14)
==3099== by 0x80A5CC6: Ser::method() (in /home/user)
==3099== by 0x80BCA61: bool Ser() (in /home/user)
==3099== by 0x80958D1: Ser::Select() (in /home/user)
==3099== by 0x804B85D: main (in /home/user)
==3099==
==3099== Use of uninitialised value of size 4
==3099== at 0x40BA12E: ??? (in /usr/lib/libstdc++.so.6.0.14)
==3099== by 0x40BA693: std::ostreambuf_iterator<char, std::char_traits<char> > std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::_M_insert_int<long>(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, long) const (in /usr/lib/libstdc++.so.6.0.14)
==3099== by 0x40BA98C: std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::do_put(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, long) const (in /usr/lib/libstdc++.so.6.0.14)
==3099== by 0x40C5A98: std::ostream& std::ostream::_M_insert<long>(long) (in /usr/lib/libstdc++.so.6.0.14)
==3099== by 0x40C5C13: std::ostream::operator<<(int) (in /usr/lib/libstdc++.so.6.0.14)
==3099== by 0x80A5CC6: Ser::method() (in /home/user)
==3099== by 0x80BCA61: bool Ser::Call() (in /home//user)
==3099== by 0x80958D1: Ser::Select() (in /home/user)
==3099== by 0x804B85D: main (in /home/user)
What does this mean?
Where is the error?
This error means that you are working with some variables before they were initialized. Looks like you are printing uninitialized int value in Ser::method(). You should initialize it before printing.