Memory leaks when Union was allocated memory using memset - c++

For C++11 and above:
ad_tree_node refers to a Union data structure designed to hold an object of type ad_node or vary_node which are of type struct.
The code compiles but memory leaks are detected when used with valgrind.
Following is the code:
struct ad_node {
std::string tag_;
int count_;
std::vector<int> index_;
bool leaf_;
};
struct vary_node {
std::string tag_;
int index_;
int mcv_;
};
union ad_tree_node {
ad_node ad;
vary_node vy;
ad_tree_node () { std::memset(this, 0, sizeof(ad_node)); }
~ad_tree_node() {}
};
std::string print_ad_tree_node(const ad_tree_node& nd, bool is_ad_node) {
std::string st = "";
if (is_ad_node) {
st += "ad_node: " + nd.ad.tag_+ ", " + std::to_string(nd.ad.count_) + ", ";
if (nd.ad.leaf_) { st += " leaf, "; }
else { st += "non-leaf, "; }
st += "index: ";
std::cout << nd.ad.index_.size();
for (auto x : nd.ad.index_) { st += std::to_string(x) + ", "; }
}
else {
st += "vy_node: " + nd.vy.tag_ + ", mcv_: " + std::to_string(nd.vy.mcv_) + ", ";
st += "index: ";
std::cout << nd.vy.index_;
}
return st;
}
int main () {
ad_node t1;
for (int i = 0; i < 10; ++i) t1.index_.push_back(i);
t1.tag_ = "A";
t1.leaf_ = true;
t1.count_ = 9;
ad_tree_node nd;
nd.ad.tag_ = t1.tag_;
nd.ad.leaf_ = t1.leaf_;
nd.ad.count_ = t1.count_;
nd.ad.index_ = std::move(t1.index_);
std::cout << print_ad_tree_node(nd, true) << std::endl;
return 0;
}
Compiled with following flags:
g++ -std=c++11 -g3 code.cpp
valgrind --leak-check=full ./a.out
Reported leak by valgrind:
==6625== Memcheck, a memory error detector
==6625== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==6625== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==6625== Command: ./a.out
==6625==
10ad_node: A, 9, leaf, index: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
==6625==
==6625== HEAP SUMMARY:
==6625== in use at exit: 72,770 bytes in 3 blocks
==6625== total heap usage: 10 allocs, 7 frees, 73,946 bytes allocated
==6625==
==6625== 2 bytes in 1 blocks are definitely lost in loss record 1 of 3
==6625== at 0x4C2E0EF: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6625== by 0x4F593DE: std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_assign(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==6625== by 0x4F596E8: std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::operator=(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==6625== by 0x4022EA: main (code.cpp:56)
==6625==
==6625== 64 bytes in 1 blocks are definitely lost in loss record 2 of 3
==6625== at 0x4C2E0EF: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6625== by 0x40386D: __gnu_cxx::new_allocator<int>::allocate(unsigned long, void const*) (new_allocator.h:104)
==6625== by 0x403518: std::allocator_traits<std::allocator<int> >::allocate(std::allocator<int>&, unsigned long) (alloc_traits.h:491)
==6625== by 0x403257: std::_Vector_base<int, std::allocator<int> >::_M_allocate(unsigned long) (stl_vector.h:170)
==6625== by 0x402D79: void std::vector<int, std::allocator<int> >::_M_emplace_back_aux<int const&>(int const&) (vector.tcc:412)
==6625== by 0x402B24: std::vector<int, std::allocator<int> >::push_back(int const&) (stl_vector.h:923)
==6625== by 0x402295: main (code.cpp:49)
==6625==
==6625== LEAK SUMMARY:
==6625== definitely lost: 66 bytes in 2 blocks
==6625== indirectly lost: 0 bytes in 0 blocks
==6625== possibly lost: 0 bytes in 0 blocks
==6625== still reachable: 72,704 bytes in 1 blocks
==6625== suppressed: 0 bytes in 0 blocks
==6625== Reachable blocks (those to which a pointer was found) are not shown.
==6625== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==6625==
==6625== For counts of detected and suppressed errors, rerun with: -v
==6625== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)

Your destructor for ad_tree_node is just {}. Unlike normal class types, whose destructors will automatically invoke the destructors for each base class and each member object, for unions you have to do everything yourself. In this case, ~ad_tree_node() does not invoke ~ad_node(), and so all the memory allocated by the std::string and std::vector members is leaked. This is precisely what valgrind is complaining about.
You also have the problem of memset - which doesn't play nicely with non-standard-layout types. memset-ing a string or a vector is UB.
What you really want is a variant:
using ad_tree_node = variant<ad_node, vary_node>;
A variant, in C++ parlance, is like a union - except it knows which type it contains, manages its storage correctly per C++ object semantics, and cleans up after itself. For C++11, a good implementation is Boost.Variant.

Related

running test using random values crashes sometimes with SIGABT. how to expose out of array bounds error in c++

I'm trying to run the following code for a heap but I'm getting this error randomly:
*** An abort error (SIGABRT) occurred during program execution.
*** This error is thrown by system functions that detect corrupt state.
***
and was wondering why for this code:
PQHeap::PQHeap() {
_cap = 10;
_elements = new int[_cap];
_count = 0;
}
PQHeap::~PQHeap() {
delete [] _elements;
}
void PQHeap::enqueue(int elem) {
if (_count == _cap) {
_cap *= 2;
int * newHeap = new int[_cap];
for (int i = 1; i <= _count; i += 1) {
newHeap[i] = _elements[i];
}
delete [] _elements;
_elements = newHeap;
}
_count += 1;
int i = _count;
_elements[i] = elem;
if (i > _count) {
error("out of bounds on line 33 i: " + integerToString(i));
cout << "out of bounds on line 33 i: " + integerToString(i) << endl;
} else {
if (i == 1) {
return;
}
int curr = elem;
int parentI = i / 2;
int parent = _elements[parentI];
while (i > 1 && parent > curr) {
_elements[parentI] = curr;
_elements[i] = parent;
i /= 2;
parentI /= 2;
curr = _elements[i];
parent = _elements[parentI];
}
}
}
int PQHeap::size() const {
return _count;
}
void PQHeap::clear() {
if (_count > 0) {
delete [] _elements;
}
_cap = 10;
_elements = new int[_cap];
_count = 0;
}
int PQHeap::peek() const {
if (_count > 0) {
return _elements[1];
}
error("can't peek empty heap");
}
int PQHeap::dequeue() {
if (_count == 0) {
error("can't dequeue empty queue");
} else {
int dequeued = _elements[1];
int i = 1;
if (i < 1 || i > _count) {
cout << "i is out of bounds, i: " << i << ", count: " << _count << endl;
}
int curr = _elements[_count];
_elements[i] = curr;
int child1I = 2 * i;
int child1 = _elements[child1I];
_count -= 1;
int smallerChildI = child1I;
int child2I = 2 * i + 1;
if (child2I <= _count) {
if (_elements[child2I] < child1) {
smallerChildI = child2I;
}
}
int smallerChild = _elements[smallerChildI];
while(child1I <= _count && curr > smallerChild) {
_elements[i] = _elements[smallerChildI];
_elements[smallerChildI] = curr;
i = smallerChildI;
curr = _elements[i];
child1I = 2 * i;
child1 = _elements[child1I];
smallerChildI = child1I;
child2I = 2 * i + 1;
if (child2I <= _count) {
if (_elements[child2I] < child1) {
smallerChildI = child2I;
}
}
smallerChild = _elements[smallerChildI];
}
return dequeued;
}
}
bool PQHeap::isEmpty() const {
return _count == 0;
}
I was wondering how I might be able to get better information on this. I tried to play around with removing the delete array statements to no avail. I thought it might even be an out of bounds issue. I'm not sure though with the undetailed error message I got. I also tried to translate this into Java in hopes of using its error checking but I only would periodically get an out of bounds error, though not sure where. Thank you.
Edit: I just confirmed that it was an out of bounds error as the Java code clarified. I was wondering how I might be able to expose this issue in c++ now without manually/procedurally adding it.
for (int i = 1; i <= _count; i += 1) {
That looks off. Array indices are 0-based, so [0..count-1] not [1..count]. Fixed:
for (size_t i = 0; i < _count; ++i) {
newHeap[i] = _elements[i];
}
Likewise, the explicit bounds check is wrong:
if (i < 1 || i > _count) {
cout << "i is out of bounds, i: " << i << ", count: " << _count
<< endl;
}
Should be
size_t i = 1;
if (i < 0 || i >= _count) {
There are some redundant/tautological checks:
size_t i = _count;
_elements[i] = elem;
if (i > _count) {
Can never be true. Likewise, if you used unsigned types (size_t) properly for indices, checks for <0 are redundant.
Note, your code is not exception safe, and should be using standard algorithms, but I guess this is for a class and you are not allowed to use them.
The way to find out is by using checkers:
Compile with warnings! (-Wall -Wextra -pedantic on GCC/Clang, at a minimum)
Use ASan/UBSan (GCC and Clang)
Use Valgrind
Demo: ASAN/UBSan
Compiled with -fsanitize=address,undefined, doing a simple test:
int main() {
PQHeap heap;
for (auto i : { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 12, 13, 14, 15, 16, 17, 18, 19, 20 }) {
heap.enqueue(i);
}
}
Already fails:
Line 42:
_elements[i] = elem;
So, i is out of bounds there. Turns out the condition earlier:
if (_count == _cap) {
should be
if (_count + 1 >= _cap) {
Using Valgrind
Running instead of ./sotest with valgrind ./sotest:
==29286== Memcheck, a memory error detector
==29286== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==29286== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==29286== Command: ./sotest
==29286==
==29286== Invalid write of size 4
==29286== at 0x1090C0: PQHeap::enqueue(int) (test.cpp:42)
==29286== by 0x108D97: main (test.cpp:132)
==29286== Address 0x61f2ca8 is 0 bytes after a block of size 40 alloc'd
==29286== at 0x4C3089F: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==29286== by 0x10902C: PQHeap::PQHeap() (test.cpp:24)
==29286== by 0x108D8D: main (test.cpp:129)
==29286==
==29286== Conditional jump or move depends on uninitialised value(s)
==29286== at 0x1090E4: PQHeap::enqueue(int) (test.cpp:54)
==29286== by 0x108D97: main (test.cpp:132)
==29286==
==29286==
==29286== HEAP SUMMARY:
==29286== in use at exit: 0 bytes in 0 blocks
==29286== total heap usage: 3 allocs, 3 frees, 72,824 bytes allocated
==29286==
==29286== All heap blocks were freed -- no leaks are possible
==29286==
==29286== For counts of detected and suppressed errors, rerun with: -v
==29286== Use --track-origins=yes to see where uninitialised values come from
==29286== ERROR SUMMARY: 3 errors from 2 contexts (suppressed: 0 from 0)
Points at the same line. Fixing it, and adding a dequeue loop:
while (!heap.isEmpty()) {
std::cout << heap.dequeue() << " ";
}
Prints a whole array of errors:
==1306== Memcheck, a memory error detector
==1306== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==1306== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==1306== Command: ./sotest
==1306==
==1306== Conditional jump or move depends on uninitialised value(s)
==1306== at 0x10916A: PQHeap::enqueue(int) (test.cpp:54)
==1306== by 0x108DE7: main (test.cpp:132)
==1306==
==1306== Use of uninitialised value of size 8
==1306== at 0x10932F: PQHeap::dequeue() (test.cpp:120)
==1306== by 0x108E07: main (test.cpp:136)
==1306==
==1306== Conditional jump or move depends on uninitialised value(s)
==1306== at 0x1092F9: PQHeap::dequeue() (test.cpp:106)
==1306== by 0x108E07: main (test.cpp:136)
==1306==
==1306== Use of uninitialised value of size 8
==1306== at 0x109307: PQHeap::dequeue() (test.cpp:107)
==1306== by 0x108E07: main (test.cpp:136)
==1306==
==1306== Conditional jump or move depends on uninitialised value(s)
==1306== at 0x10931E: PQHeap::dequeue() (test.cpp:115)
==1306== by 0x108E07: main (test.cpp:136)
==1306==
==1306== Conditional jump or move depends on uninitialised value(s)
==1306== at 0x1092FE: PQHeap::dequeue() (test.cpp:106)
==1306== by 0x108E07: main (test.cpp:136)
==1306==
==1306== Use of uninitialised value of size 8
==1306== at 0x10930E: PQHeap::dequeue() (test.cpp:107)
==1306== by 0x108E07: main (test.cpp:136)
==1306==
==1306== Conditional jump or move depends on uninitialised value(s)
==1306== at 0x515F7AB: 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/x86_64-linux-gnu/libstdc++.so.6.0.28)
==1306== by 0x516DC55: std::ostream& std::ostream::_M_insert<long>(long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
==1306== by 0x108E11: main (test.cpp:136)
==1306==
==1306== Use of uninitialised value of size 8
==1306== at 0x515F4F3: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
==1306== by 0x515F7D5: 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/x86_64-linux-gnu/libstdc++.so.6.0.28)
==1306== by 0x516DC55: std::ostream& std::ostream::_M_insert<long>(long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
==1306== by 0x108E11: main (test.cpp:136)
==1306==
==1306== Conditional jump or move depends on uninitialised value(s)
==1306== at 0x515F505: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
==1306== by 0x515F7D5: 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/x86_64-linux-gnu/libstdc++.so.6.0.28)
==1306== by 0x516DC55: std::ostream& std::ostream::_M_insert<long>(long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
==1306== by 0x108E11: main (test.cpp:136)
==1306==
==1306== Conditional jump or move depends on uninitialised value(s)
==1306== at 0x515F80A: 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/x86_64-linux-gnu/libstdc++.so.6.0.28)
==1306== by 0x516DC55: std::ostream& std::ostream::_M_insert<long>(long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
==1306== by 0x108E11: main (test.cpp:136)
==1306==
==1306== Use of uninitialised value of size 8
==1306== at 0x109320: PQHeap::dequeue() (test.cpp:117)
==1306== by 0x108E07: main (test.cpp:136)
==1306==
==1306== Use of uninitialised value of size 8
==1306== at 0x109324: PQHeap::dequeue() (test.cpp:117)
==1306== by 0x108E07: main (test.cpp:136)
==1306==
==1306== Use of uninitialised value of size 8
==1306== at 0x1092F2: PQHeap::dequeue() (test.cpp:105)
==1306== by 0x108E07: main (test.cpp:136)
==1306==
1 2 0 3 4 0 5 6 7 8 10 11 12 13 14 15 16 17 18 i is out of bounds, i: 1, count: 1
20 ==1306==
==1306== HEAP SUMMARY:
==1306== in use at exit: 0 bytes in 0 blocks
==1306== total heap usage: 5 allocs, 5 frees, 74,008 bytes allocated
==1306==
==1306== All heap blocks were freed -- no leaks are possible
==1306==
==1306== For counts of detected and suppressed errors, rerun with: -v
==1306== Use --track-origins=yes to see where uninitialised values come from
==1306== ERROR SUMMARY: 56 errors from 14 contexts (suppressed: 0 from 0)
Just take them, 1 at a time.
while (i > 1 && parent > curr) {
depends on unitialized data. Which means that _elements[parentI] must be a location never written to (parentI is out of bounds?). Nah, parentI can't be out of bounds. In fact, it is likely 0. Which means, that we're off-by-one again. And indeed:
_count += 1;
size_t i = _count;
_elements[i] = elem;
Writes the first element to index 1, not 0. You'll get the rest, no doubt :/
Many Fixes:
This will still have errors, but you might want to see what caught my eye:

C++ Poco MySQL Data wrapper segmentation fault error

I am using Poco 1.8 Data library. I want to build a database wrapper to run multiple SQL queries concurrently.
I build a dbconn.h with the following.
std::string _dbConnString = "host=" + host + ";user=" + user + ";password=" + password + ";db="+db
+";compress=true;auto-reconnect=true";
std::string getkey(int userID, int exchangeID) {
Poco::Data::MySQL::Connector::registerConnector();
std::string key;
{
// 0. connect & create table
Session session(Poco::Data::MySQL::Connector::KEY,_dbConnString);
Statement selectn(session);
selectn << "SELECT key FROM API WHERE user_id=? ", into(key), use(userID), now;
}
catch (const Poco::Data::ConnectionFailedException &ce)
{
std::cout << ce.displayText() << std::endl;
}
catch (const Poco::Data::MySQL::StatementException &se)
{
std::cout << se.displayText() << std::endl;
}
Poco::Data::MySQL::Connector::unregisterConnector();
return key;
}
std::string getuser(int userID, int exchangeID) {
Poco::Data::MySQL::Connector::registerConnector();
std::string user;
try
{
// 0. connect & create table
Session session(Poco::Data::MySQL::Connector::KEY, _dbConnString);
Statement selectn(session);
selectn << "SELECT user FROM API WHERE user_id=? ", into(user), use(userID), now;
}
catch (const Poco::Data::ConnectionFailedException &ce)
{
std::cout << ce.displayText() << std::endl;
}
catch (const Poco::Data::MySQL::StatementException &se)
{
std::cout << se.displayText() << std::endl;
}
Poco::Data::MySQL::Connector::unregisterConnector();
return user;
}
The following will throw out segmental fault.
teset.cpp
int user_id = 100;
int exchange_id = 1;
std::string key = getkey(user_id,exchange_id); //no error
std::string user = getuser(user_id,exchange_id); //segmentation fault
If you reverse the order of the function call, same error:
std::string user = getuser(user_id,exchange_id); //no error
std::string key = getkey(user_id,exchange_id); //segmentation fault
I think something to do with the the part of creating the session. But there is not so many Poco data examples available on internet, any advice is appreciated.
Valgrind error:
==3316== Thread 2:
==3316== Invalid read of size 4
==3316== at 0x4E45FA0: pthread_mutex_lock (pthread_mutex_lock.c:65)
==3316== by 0x76332D9: ??? (in /usr/lib/x86_64-linux-gnu/libmysqlclient.so.20.3.12)
==3316== by 0x760AB40: ??? (in /usr/lib/x86_64-linux-gnu/libmysqlclient.so.20.3.12)
==3316== by 0x75DEB2A: mysql_real_connect (in /usr/lib/x86_64-linux-gnu/libmysqlclient.so.20.3.12)
==3316== by 0x5B43736: Poco::Data::MySQL::SessionHandle::connect(char const*, char const*, char const*, char const*, unsigned int) (in /usr/lib/libPocoDataMySQL.so.50)
==3316== by 0x5B4795A: Poco::Data::MySQL::SessionImpl::open(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (in /usr/lib/libPocoDataMySQL.so.50)
==3316== by 0x5B48D86: Poco::Data::MySQL::SessionImpl::SessionImpl(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned long) (in /usr/lib/libPocoDataMySQL.so.50)
==3316== by 0x5B3E51D: Poco::Data::MySQL::Connector::createSession(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned long) (in /usr/lib/libPocoDataMySQL.so.50)
==3316== by 0x5498B83: Poco::Data::SessionFactory::create(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned long) (in /usr/lib/libPocoData.so.50)
==3316== by 0x115048: getAPIsecret[abi:cxx11](int, int) (dbconnector.h:85)
==3316== by 0x11561A: Trading::Binance::BUY::process(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (binance.cpp:36)
==3316== by 0x110F95: Trading::ExchangeRequest::run() (exchangeRequest.cpp:58)
==3316== Address 0x30 is not stack'd, malloc'd or (recently) free'd
==3316==
==3316==
==3316== Process terminating with default action of signal 11 (SIGSEGV)
==3316== Access not within mapped region at address 0x30
==3316== at 0x4E45FA0: pthread_mutex_lock (pthread_mutex_lock.c:65)
==3316== by 0x76332D9: ??? (in /usr/lib/x86_64-linux-gnu/libmysqlclient.so.20.3.12)
==3316== by 0x760AB40: ??? (in /usr/lib/x86_64-linux-gnu/libmysqlclient.so.20.3.12)
==3316== by 0x75DEB2A: mysql_real_connect (in /usr/lib/x86_64-linux-gnu/libmysqlclient.so.20.3.12)
==3316== by 0x5B43736: Poco::Data::MySQL::SessionHandle::connect(char const*, char const*, char const*, char const*, unsigned int) (in /usr/lib/libPocoDataMySQL.so.50)
==3316== by 0x5B4795A: Poco::Data::MySQL::SessionImpl::open(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (in /usr/lib/libPocoDataMySQL.so.50)
==3316== by 0x5B48D86: Poco::Data::MySQL::SessionImpl::SessionImpl(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned long) (in /usr/lib/libPocoDataMySQL.so.50)
==3316== by 0x5B3E51D: Poco::Data::MySQL::Connector::createSession(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned long) (in /usr/lib/libPocoDataMySQL.so.50)
==3316== by 0x5498B83: Poco::Data::SessionFactory::create(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned long) (in /usr/lib/libPocoData.so.50)
==3316== by 0x115048: getAPIsecret[abi:cxx11](int, int) (dbconnector.h:85)
==3316== by 0x11561A: Trading::Binance::BUY::process(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (binance.cpp:36)
==3316== by 0x110F95: Trading::ExchangeRequest::run() (exchangeRequest.cpp:58)
==3316== If you believe this happened as a result of a stack
==3316== overflow in your program's main thread (unlikely but
==3316== possible), you can try to increase the size of the
==3316== main thread stack using the --main-stacksize= flag.
==3316== The main thread stack size used in this run was 8388608.
==3316==
==3316== HEAP SUMMARY:
==3316== in use at exit: 266,548 bytes in 966 blocks
==3316== total heap usage: 2,241 allocs, 1,275 frees, 790,945 bytes allocated
==3316==
==3316== LEAK SUMMARY:
==3316== definitely lost: 0 bytes in 0 blocks
==3316== indirectly lost: 0 bytes in 0 blocks
==3316== possibly lost: 62,545 bytes in 63 blocks
==3316== still reachable: 204,003 bytes in 903 blocks
==3316== suppressed: 0 bytes in 0 blocks
==3316== Rerun with --leak-check=full to see details of leaked memory
==3316==
==3316== For counts of detected and suppressed errors, rerun with: -v
==3316== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
The Poco::Data::MySQL::Connector::registerConnector(); and Poco::Data::MySQL::Connector::unregisterConnector(); have non-local effects, you should move them out of the concurrently-called bits into some global setup/teardown. And it should be enough to call them once, you don't have to repeat them for every query.

push_back a pointer of object results in segfault

The following code is to move the "non-overlapping" TablePath from vector v to vector u. I am encountering segmentaion fault at the line "u.push_back(*it1);". I didn't copy the object(but instead only copy the pointer of the object) so I believe the problem doesn't lie in copying constructor. Can you give some hints on why segfault is occuring ?
#include <iostream>
#include <vector>
using namespace std;
class TablePath
{
private:
int source;
int destination;
public:
TablePath(int,int);
~TablePath();
int overlap(TablePath*);
void toString();
TablePath(const TablePath& that) : source(that.source), destination(that.destination)
{
}
};
TablePath::TablePath(int source=0,int destination=0)
{
this->source = source;
this->destination = destination;
}
int TablePath::overlap(TablePath* thatTablePath)
{
if (this->source >= thatTablePath->source and this->source <= thatTablePath->destination)
return 1;
else if (this->destination >= thatTablePath->source and this->destination <= thatTablePath->destination)
return 1;
else if (thatTablePath->source >= this->source and thatTablePath->source <= this->destination)
return 1;
else if (thatTablePath->destination >= this->source and thatTablePath->destination <= this->destination)
return 1;
else
return 0;
}
void TablePath::toString()
{
cout << this->source << " " << this->destination << endl;
}
int main()
{
int numofTests;
cin >> numofTests;
while(numofTests > 0)
{
int numofMoves;
vector<TablePath *> v;
cin >> numofMoves;
for (int i=0;i<numofMoves;i++)
{
int source,destination;
cin >> source >> destination;
TablePath* MyTablePath = new TablePath(source,destination);
v.push_back(MyTablePath);
}
vector<TablePath *> u;
vector<TablePath *>::iterator it1 = v.begin();
u.push_back(*it1);
v.erase(v.begin());
for(vector<TablePath *>::iterator it1 = v.begin(); it1 != v.end(); ++it1)
{
for(vector<TablePath *>::iterator it2 = u.begin(); it2 != u.end(); ++it2)
{
if ((*it1)->overlap((*it2)))
{
u.push_back(*it1);
}
}
}
cout << u.size() * 10;
v.erase(v.begin(),v.end());
u.erase(u.begin(),u.end());
numofTests--;
}
}
The following is the output I get from valgrind:
frank#frank-vm:~$ valgrind --tool=memcheck ./tablepath
==6172== Memcheck, a memory error detector
==6172== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==6172== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==6172== Command: ./tablepath
==6172==
1
3
10
20
15 30
20 50
==6172== Invalid read of size 4
==6172== at 0x8048BB0: main (in /home/frank/tablepath)
==6172== Address 0x4320184 is 0 bytes after a block of size 4 free'd
==6172== at 0x402ACFC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==6172== by 0x8049616: __gnu_cxx::new_allocator<TablePath*>::deallocate(TablePath**, unsigned int) (in /home/frank/tablepath)
==6172== by 0x80493E8: std::_Vector_base<TablePath*, std::allocator<TablePath*> >::_M_deallocate(TablePath**, unsigned int) (in /home/frank/tablepath)
==6172== by 0x8049230: std::vector<TablePath*, std::allocator<TablePath*> >::_M_insert_aux(__gnu_cxx::__normal_iterator<TablePath**, std::vector<TablePath*, std::allocator<TablePath*> > >, TablePath* const&) (in /home/frank/tablepath)
==6172== by 0x8048E00: std::vector<TablePath*, std::allocator<TablePath*> >::push_back(TablePath* const&) (in /home/frank/tablepath)
==6172== by 0x8048BED: main (in /home/frank/tablepath)
==6172==
==6172== Invalid read of size 4
==6172== at 0x8048965: TablePath::overlap(TablePath*) (in /home/frank/tablepath)
==6172== by 0x8048BCA: main (in /home/frank/tablepath)
==6172== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==6172==
==6172==
==6172== Process terminating with default action of signal 11 (SIGSEGV)
==6172== Access not within mapped region at address 0x0
==6172== at 0x8048965: TablePath::overlap(TablePath*) (in /home/frank/tablepath)
==6172== by 0x8048BCA: main (in /home/frank/tablepath)
==6172== If you believe this happened as a result of a stack
==6172== overflow in your program's main thread (unlikely but
==6172== possible), you can try to increase the size of the
==6172== main thread stack using the --main-stacksize= flag.
==6172== The main thread stack size used in this run was 8388608.
==6172==
==6172== HEAP SUMMARY:
==6172== in use at exit: 48 bytes in 5 blocks
==6172== total heap usage: 8 allocs, 3 frees, 64 bytes allocated
==6172==
==6172== LEAK SUMMARY:
==6172== definitely lost: 0 bytes in 0 blocks
==6172== indirectly lost: 0 bytes in 0 blocks
==6172== possibly lost: 0 bytes in 0 blocks
==6172== still reachable: 48 bytes in 5 blocks
==6172== suppressed: 0 bytes in 0 blocks
==6172== Rerun with --leak-check=full to see details of leaked memory
==6172==
==6172== For counts of detected and suppressed errors, rerun with: -v
==6172== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
Segmentation fault (core dumped)
std::vector<T>::push_back is (usually) allowed to invalidate all iterators associated with the vector object. So after you do:
u.push_back(*it1);
it is not safe to continue the inner for loop with ++it2.
You could use an index for the inner loop instead. Or, break out of the inner loop right after doing the push_back, if you don't really want multiple copies of the same TablePath* pointer in u.

~vector() causes SIGSEGV when exit

Thats the Store Credit problem on Google code jam.
https://code.google.com/codejam/contest/351101/dashboard#s=p0
My code gives out a SIGSEGV after running the large test. But the answer is correct!
#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;
int ps[1000]={0};
vector<int> indice[1000];
int main() {
int cases; scanf("%d", &cases);
for(int j=1;j<=cases;j++) {
printf("Case #%d: ", j);
int c, is; scanf("%d%d", &c, &is);
for(int i=0;i<=c;i++) ps[i]=0;
for(int i=0;i<=c;i++) indice[i].clear();
for (int i = 0; i < is; i++) {
int it; scanf("%d", &it);
indice[it].push_back(i+1);
ps[it]=1;
if (c-it>0&&ps[c-it]) {
int a, b;
a = indice[it][0];
b = indice[c-it][0];
if(c==2*it&&indice[it].size()>1) {
b=indice[it][1];
}
if (a!=b) {
printf("%d %d\n", min(a,b),max(a,b));
}
}
}
}
return 0;
}
So I use valgrind to find out what's going on .. but it seems that it's not my problem.
==17599== Invalid free() / delete / delete[] / realloc()
==17599== at 0x4C2A4BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==17599== by 0x401669: __gnu_cxx::new_allocator<int>::deallocate(int*, unsigned long) (new_allocator.h:98)
==17599== by 0x4013CD: std::_Vector_base<int, std::allocator<int> >::_M_deallocate(int*, unsigned long) (stl_vector.h:156)
==17599== by 0x400F60: std::_Vector_base<int, std::allocator<int> >::~_Vector_base() (stl_vector.h:142)
==17599== by 0x400D8D: std::vector<int, std::allocator<int> >::~vector() (stl_vector.h:351)
==17599== by 0x400C48: __tcf_0 (a.cpp:6)
==17599== by 0x5383900: __run_exit_handlers (exit.c:78)
==17599== by 0x5383984: exit (exit.c:100)
==17599== by 0x5369773: (below main) (libc-start.c:258)
==17599== Address 0x1 is not stack'd, malloc'd or (recently) free'd
==17599==
==17599==
==17599== HEAP SUMMARY:
==17599== in use at exit: 128 bytes in 1 blocks
==17599== total heap usage: 4,527 allocs, 4,527 frees, 113,664 bytes allocated
==17599==
==17599== LEAK SUMMARY:
==17599== definitely lost: 0 bytes in 0 blocks
==17599== indirectly lost: 0 bytes in 0 blocks
==17599== possibly lost: 0 bytes in 0 blocks
==17599== still reachable: 128 bytes in 1 blocks
==17599== suppressed: 0 bytes in 0 blocks
==17599== Rerun with --leak-check=full to see details of leaked memory
==17599==
==17599== For counts of detected and suppressed errors, rerun with: -v
==17599== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 2 from 2)
I'm so confused... Could anybody tell me what's going on? I'm a newbie of C++ ..
Thank you very much.
As I understand valgrind, it can't detect that you are writing outside of the bounds of arrays that are staticly allocated. So let's allocate them on the heap.
vector<int> *indice = new vector<int>[1000];
int *ps = new int[1000];
Then, you will see errors come out of valgrind. Including:
==7168== Invalid read of size 8
==7168== at 0x4008D6: main (stl_vector.h:735)
==7168== Address 0x4c39e10 is 8 bytes after a block of size 24,008 alloc'd
==7168== at 0x4A07152: operator new[](unsigned long) (vg_replace_malloc.c:363)
==7168== by 0x400791: global constructors keyed to indice (foo.cc:6)
==7168== by 0x400C35: ??? (in /tmp/foo)
==7168== by 0x4005F2: ??? (in /tmp/foo)
==7168==
==7168== Invalid read of size 8
==7168== at 0x4008DA: main (stl_vector.h:735)
==7168== Address 0x4c39e18 is 16 bytes after a block of size 24,008 alloc'd
==7168== at 0x4A07152: operator new[](unsigned long) (vg_replace_malloc.c:363)
==7168== by 0x400791: global constructors keyed to indice (foo.cc:6)
==7168== by 0x400C35: ??? (in /tmp/foo)
==7168== by 0x4005F2: ??? (in /tmp/foo)
==7168==
And using gdb, I can see that the SIGSEGV occurs when you access indice[1433], which is outside of the bounds of indice.
I also imagine that your actual issue is that for the large dataset, the variables bounds are listed as:
N = 50
3 ≤ I ≤ 2000
Are you sure you shouldn't be allocating 2001 elements, instead of 1000?

Why am I getting a segmentation fault? Valgrind?

I have written a program to determine the longest common subsequence between two strings. I have tested my function LCSLength() with a small hard coded test case and it returns the correct value.
Now, I am reading strings from a file to compare, and my program gives me a segmentation fault. Here is the code:
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
using namespace std;
int LCSLength(string X,string Y);
int main()
{
ifstream inData("sequences.dat");
vector<string> lines(1);
string line;
int LCS;
while (getline(inData,line))
{
if (line.empty())
lines.push_back("");
else
lines.back() += line;
}
LCS = LCSLength(lines[0],lines[1]);
cout << "The LCS is: " << LCS << endl;
return 0;
}
int LCSLength(string X,string Y)
{
int m = X.size();
int n = Y.size();
int L[m+1][n+1];
for(int i=0; i<=m; i++)
{
for(int j=0; j<=n; j++)
{
if(i==0 || j==0)
L[i][j] = 0;
else if(X[i-1]==Y[j-1])
L[i][j] = L[i-1][j-1]+1;
else
L[i][j] = max(L[i-1][j],L[i][j-1]);
}
}
return L[m][n];
}
When I compile using -pedantic -ansi, I get the following error: In function LCSLength(std::string, std::string): ISO C++ forbids variable size array 'L'.
I compiled using Valgrind, and here are the errors it produced:
==15183== LEAK SUMMARY:
==15183== definitely lost: 8,624 bytes in 14 blocks
==15183== indirectly lost: 1,168 bytes in 5 blocks
==15183== possibly lost: 5,518 bytes in 58 blocks
==15183== still reachable: 44,925 bytes in 278 blocks
==15183== suppressed: 0 bytes in 0 blocks
==15183== Reachable blocks (those to which a pointer was found) are not shown.
==15183== To see them, rerun with: --leak-check=full --show-reachable=yes
==15183==
==15183== ERROR SUMMARY: 23 errors from 23 contexts (suppressed: 0 from 0)
==15183==
==15183== 1 errors in context 1 of 23:
==15183== Invalid read of size 4
==15183== at 0x38326: std::string::_Rep::_M_grab(std::allocator<char> const&, std::allocator<char> const&) (in /usr/lib/libstdc++.6.0.9.dylib)
==15183== by 0x388EF: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::string const&) (in /usr/lib/libstdc++.6.0.9.dylib)
==15183== by 0x100001AAE: main (firstt.cpp:23)
==15183== Address 0xfffffffffffffff8 is not stack'd, malloc'd or (recently) free'd
==15183==
==15183==
==15183== 1 errors in context 2 of 23:
==15183== Invalid read of size 8
==15183== at 0x388DC: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::string const&) (in /usr/lib/libstdc++.6.0.9.dylib)
==15183== by 0x100001AAE: main (firstt.cpp:23)
==15183== Address 0x100023d28 is 0 bytes after a block of size 8 alloc'd
==15183== at 0x5237: malloc (in /usr/local/Cellar/valgrind/3.8.1/lib/valgrind/vgpreload_memcheck-amd64-darwin.so)
==15183== by 0x4B346: operator new(unsigned long) (in /usr/lib/libstdc++.6.0.9.dylib)
==15183== by 0x100002DFE: __gnu_cxx::new_allocator<std::string>::allocate(unsigned long, void const*) (new_allocator.h:91)
==15183== by 0x100002E42: std::_Vector_base<std::string, std::allocator<std::string> >::_M_allocate(unsigned long) (stl_vector.h:131)
==15183== by 0x100002E9D: std::_Vector_base<std::string, std::allocator<std::string> >::_Vector_base(unsigned long, std::allocator<std::string> const&) (stl_vector.h:116)
==15183== by 0x1000030E4: std::vector<std::string, std::allocator<std::string> >::vector(unsigned long, std::string const&, std::allocator<std::string> const&) (stl_vector.h:215)
==15183== by 0x1000017D9: main (firstt.cpp:11)
==15183==
==15183== ERROR SUMMARY: 23 errors from 23 contexts (suppressed: 0 from 0)
Segmentation fault: 11
My test file has two lines of sequences. I check lines.size() and it returns 2. I also cout << lines[0] and cout << lines[1] and the correct strings are printed.
Can anyone help me figure this out? Thanks.
your lines vector always contains one element, therefore accesing it by index 1 causes UB
LCS = LCSLength(lines[0],lines[1]);
here ^
Did you confirm that after exiting the while loop, both lines[0] and lines[1] exist? This will happen only if you have at least one empty line in your input file (and recognized as such).
According to Valgrind (do read its output!) - you are doing something wrong from within main (lines 11 or 23) and not from LCSLength.