C++ - segmentation fault on second binary search - c++

I have a class ledger, whose instances are supposed to store instances of a member class company in two vectors combyID and combyname, sorted by two different criteria - ID and name (both are strings). The vectors start out empty, so instead of sorting them after each new addition of an instance of the member class, a customized binary search methods binsID and binsName search the vectors for the element to be added and if the element isn't found, it is inserted in the vectors. The insert() position is defined by the idx value, modified by the binary search method.
The problem lies within the method NewCo, which calls both binary search methods and eventually inserts the element to the vectors. When the program is run with more than just one NewCo call in the main function, Segmentation fault (core dumped) error is given. The error doesn't appear either if the binsID method isn't called or the insert() isn't called on combyID (omitting the insertion to that vector). I am posting both the code and the valgrind analysis.
The code:
#include <cstdlib>
#include <cstdio>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class ledger
{
public:
bool NewCo (string name, string ID)
{
unsigned int idx_id = 0, idx_name = 0;
bool found1 = binsID(combyID, idx_id, ID); //line 14
bool found2 = binsName(combyname, idx_name, name);
if (found1 == false && found2 == false)
{
company co;
co.co_name = name;
co.co_id = ID;
combyID.insert(combyID.begin() + idx_id, co);
combyname.insert(combyname.begin() + idx_name, co);
return 1;
}
return 0;
}
private:
class company
{
public:
string co_name;
string co_id;
};
vector <company> combyID;
vector <company> combyname;
bool binsName(vector <company> vek, unsigned int & idx, string val)
{
if (vek.size() == 0) return false;
unsigned int begin = 0, end = vek.size() - 1, mid;
while(begin <= end)
{
mid = (begin + end) / 2;
idx = mid;
if (vek[mid].co_name == val)
{
idx = mid;
return true;
}
else if (val < vek[mid].co_name)
end = mid - 1;
else
begin = mid + 1;
}
if (vek[idx].co_name < val) idx++;
return false;
}
bool binsID(vector <company> vek, unsigned int & idx, string val)
{
if (vek.size() == 0) return false;
unsigned int begin = 0, end = vek.size() - 1, mid;
while(begin <= end)
{
mid = (begin + end) / 2;
idx = mid;
if (vek[mid].co_id == val) //line 66
{
idx = mid;
return true;
}
else if (val < vek[mid].co_id)
end = mid - 1;
else
begin = mid + 1;
}
if (vek[idx].co_id < val) idx++;
return false;
}
};
int main ( void )
{
ledger b1;
b1.NewCo( "ABC", "123.456.789" );
b1.NewCo( "DEF", "123.456" ); //line 85
return 0;
}
Valgrind:
==6775== Command: ./a.out -g
==6775==
==6775== Invalid read of size 8
==6775== at 0x4F597B0: std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::size() const (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==6775== by 0x401C2A: __gnu_cxx::__enable_if<std::__is_char<char>::__value, bool>::__type std::operator==<char>(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&) (basic_string.h:4913)
==6775== by 0x40177B: ledger::binsID(std::vector<ledger::company, std::allocator<ledger::company> >, unsigned int&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) (main.cpp:66)
==6775== by 0x40138B: ledger::NewCo(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) (main.cpp:14)
==6775== by 0x40109E: main (main.cpp:85)
==6775== Address 0x2005ab5d68 is not stack'd, malloc'd or (recently) free'd
==6775==
==6775==
==6775== Process terminating with default action of signal 11 (SIGSEGV)
==6775== Access not within mapped region at address 0x2005AB5D68
==6775== at 0x4F597B0: std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::size() const (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==6775== by 0x401C2A: __gnu_cxx::__enable_if<std::__is_char<char>::__value, bool>::__type std::operator==<char>(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&) (basic_string.h:4913)
==6775== by 0x40177B: ledger::binsID(std::vector<ledger::company, std::allocator<ledger::company> >, unsigned int&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) (main.cpp:66)
==6775== by 0x40138B: ledger::NewCo(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) (main.cpp:14)
==6775== by 0x40109E: main (main.cpp:85)
==6775== If you believe this happened as a result of a stack
==6775== overflow in your program's main thread (unlikely but
==6775== possible), you can try to increase the size of the
==6775== main thread stack using the --main-stacksize= flag.
==6775== The main thread stack size used in this run was 8388608.
==6775==
==6775== HEAP SUMMARY:
==6775== in use at exit: 72,896 bytes in 4 blocks
==6775== total heap usage: 4 allocs, 0 frees, 72,896 bytes allocated
==6775==
==6775== LEAK SUMMARY:
==6775== definitely lost: 0 bytes in 0 blocks
==6775== indirectly lost: 0 bytes in 0 blocks
==6775== possibly lost: 0 bytes in 0 blocks
==6775== still reachable: 72,896 bytes in 4 blocks
==6775== suppressed: 0 bytes in 0 blocks
==6775== Rerun with --leak-check=full to see details of leaked memory
==6775==
==6775== For counts of detected and suppressed errors, rerun with: -v
==6775== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Segmentation fault (core dumped)

You'll want to review your algorithms in both binsName() and binsID() methods.
For your second pass, the statement:
end = mid - 1;
is producing an end value of -1 (or in this case, UINT_MAX since you're using unsigned integers) as the value of mid is 0.

Related

std::string::append crashes program with "std::bad_alloc"

I have a text file which contains a list of data relating to name, position, and height. My program parses this data into a vector map, then uses this data to construct an xml file using boost::property_tree. The text file is about 3500 lines, and the program consistently crashes at line 1773 with:
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
Aborted (core dumped)
At first I thought maybe the size limit was being reached, but reading up on std::string shows that the target computer should be able to allocate the size required. Regardless, I decided to test with std::string::size , std::string::length, std::string::capacity, std::string::max_size which showed (respectively):
...
...
6572094845 6572094845 6626476032 9223372036854775807
6579537815 6579537815 6626476032 9223372036854775807
6586984998 6586984998 6626476032 9223372036854775807
6594436394 6594436394 6626476032 9223372036854775807
6601892003 6601892003 6626476032 9223372036854775807
6609351825 6609351825 6626476032 9223372036854775807
6616815856 6616815856 6626476032 9223372036854775807
6624284100 6624284100 6626476032 9223372036854775807
std::string::capacity was seen to increase once std::string::length == std::string::capacity.
gdb bt after compiling for debug:
(gdb) bt
#0 __GI_raise (sig=sig#entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#1 0x00007fd67037e921 in __GI_abort () at abort.c:79
#2 0x00007fd6709d3957 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3 0x00007fd6709d9ae6 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#4 0x00007fd6709d9b21 in std::terminate() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#5 0x00007fd6709d9d54 in __cxa_throw () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#6 0x00007fd6709da2dc in operator new(unsigned long) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#7 0x00007fd670a6bb8b in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_mutate(unsigned long, unsigned long, char const*, unsigned long) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#8 0x00007fd670a6d133 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_append(char const*, unsigned long) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#9 0x000056104c176f3a in main (argc=1, argv=0x7ffc0af8b9a8) at /home/code/hello_world/createWorld.cpp:224
Example line in text file being read:
713.258 235.418 ABCD1234567 2898
Code:
int main(int argc, char **argv)
{
CreateWorld *newWorld = new CreateWorld();
lastModelsParser *lastModels = new lastModelsParser();
/*
Code here reads creates ifs for xml data,
then reads xml successfully into a ptree
*/
vector<lastModelsParser::lastModel> _lastModels;
_lastModels = lastModels->getlastModels();
uint16_t lastModelsEntry = 0;
std::string newModelString;
for(auto i:_lastModels){
ptNewModel = newWorld->modelModifier(ptModel,
_lastModels.at(lastModelsEntry).pX,
_lastModels.at(lastModelsEntry).pY,
_lastModels.at(lastModelsEntry).name,
_lastModels.at(lastModelsEntry).height);
boost::property_tree::xml_parser::write_xml_element(modelOSS, ptNewModel.front().first, ptNewModel.back().second, 1, xml_settings);
newModelString.append(modelOSS.str()); // CRASHES HERE
lastModelsEntry++;
}
// append to world.xml
boost::property_tree::write_xml(worldOSS, ptWorld, xml_settings); // write xml data into OSStreams
boost::property_tree::write_xml(modelOSS, ptModel, xml_settings); // write xml data into OSStreams
size_t worldPos = worldOSS.str().find("</world>");
std::string newWorldString = worldOSS.str().insert(worldPos,newModelString+"\n\t");
newWorldFile << newWorldString ;
delete(lastModels);
delete(newWorld);
return EXIT_SUCCESS;
}
Edit. Valgrind output
valgrind --tool=massif --massif-out-file=memleak.txt ./createNewWorld
heap_tree=detailed
n2: 6636657886 (heap allocation functions) malloc/new/new[], --alloc-fns, etc.
n2: 6626476282 0x5160B89: std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_mutate(unsigned long, unsigned long, char const*, unsigned long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
n2: 6626476282 0x5162131: std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_append(char const*, unsigned long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
n0: 6626476033 0x149F38: main (in /home/code/hello_world/createNewWorld)
n0: 249 in 2 places, all below massif's threshold (1.00%)
n0: 0 in 2 places, all below massif's threshold (1.00%)
n0: 10181604 in 18 places, all below massif's threshold (1.00%)
valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --verbose --log-file=valgrind-out_1.txt ./createNewWorld
...
--4758-- memcheck GC: 1000 nodes, 0 survivors (0.0%)
--4758-- memcheck GC: 1000 nodes, 0 survivors (0.0%)
--4758-- memcheck GC: 1000 nodes, 0 survivors (0.0%)
--4758-- memcheck GC: 1000 nodes, 0 survivors (0.0%)
==4758== Warning: set address range perms: large range [0xee015040, 0x1b37d5041) (undefined)
std::string::max_size is not the biggest string your system can allocate. It's only the biggest string the std::string class itself could represent at all, given unlimited continuous memory space.
You are exceeding already more than 6GB, and there's a good chance there is simply not enough memory left to do the copy necessary for the next re-alloc. DO you have the 13GB RAM required for that step, and do your configured kernel limits permit allocation (not even commitment yet!) of that much for a single process?
Just avoid storing everything in a single, long string, but partition it / write out much earlier. Then re-allocations only result in memory usage spikes up to 2x the biggest allocation, and not 2x your total current memory consumption.
The cause for crash in this code was due to the following lines fibbonaci'ing itself on each iteration:
boost::property_tree::xml_parser::write_xml_element(modelOSS, ptNewModel.front().first, ptNewModel.back().second, 1, xml_settings);
newModelString.append(modelOSS.str());
So to explain:
On each iteration, the write_xml_element member function was writing into modelOSS then appending it to newModelString.
modelOSS is not "overwritten" and is instead appended to by default.
This appended stream is then appended onto newModelString.
Based off this, you can completely remove the line newModelString.append(modelOSS.str()); and it will function as normal.
For example this is what was happening:
New entry = "A"
it = 0, modelOSS = "A", newModelString = "A"
New entry = "B"
it = 1, modelOSS = "A, B", newModelString = "A, A, B"
new entry = "C"
it = 2, modelOSS = "A, B, C", newModelString = "A, A, B, A, A, B, C"
#1 0x00007f64df15bba8 in abort () from /lib64/libc.so.6
#2 0x00007f64ddc36e20 in ?? () from /lib64/libstdc++.so.6
#3 0x00007f64ddc44f26 in ?? () from /lib64/libstdc++.so.6
#4 0x00007f64ddc44fe1 in std::terminate() () from /lib64/libstdc++.so.6
#5 0x00007f64ddc45378 in __cxa_throw () from /lib64/libstdc++.so.6
#6 0x00007f64ddc36a7d in ?? () from /lib64/libstdc++.so.6
#7 0x00007f64ddcfbe1d in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_mutate(unsigned long, unsigned long, char const*, unsigned long) ()
from /lib64/libstdc++.so.6
#8 0x00007f64ddcfe51b in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_append(char const*, unsigned long) () from /lib64/libstdc++.so.6
#9 0x00007f63f4627d2a in encoder::xxx::xxx(std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, encoder::TileInfo, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, encoder::TileInfo> > > const&, encoder::TileInfo const&, encoder::CrossTileChapters&, encoder::AddDataInfo const&) ()
bool encoder::xxx::xxx(const std::map<std::string, TileInfo> &mapTileInfos,
const TileInfo &tileInfo, CrossTileChapters &languangeTileChapters, const AddDataInfo &addInfo)
{
...
std::string language = tileInfo.tileType;
std::string addPoiName = "";
auto langCode2name = addInfo.langCode2name;
if (langCode2name.find(language) != langCode2name.end()) {
addPoiName = langCode2name[language];
}
std::string labels = languangeTileChapters.labelChapter->GetLablesString();
...
unsigned int languangeTileLabelCount = languangeTileChapters.labelChapter->GetLabelCount();
unsigned int nativeLabelCount = poiTileChapters.labelChapter->GetNativeLabelCount();
int offset = -1;
bool isFounded = false;
offset = GetPOIOffset(poiTileChapters.pointChapter, addInfo.poiSiteID, isFounded, true);
if (isFounded) {
labels.insert(labels.end(), nativeLabelCount - languangeTileLabelCount - 1, '\0');
} else {
labels.insert(labels.end(), nativeLabelCount - languangeTileLabelCount, '\0');
}
labels += addPoiName;
labels += '\0';
languangeTileChapters.labelChapter->SetLablesString(labels);
return true;
}

BST Invalid read size

I am making a BST for a class assignment, where the Insert function and NodeData class are given. No matter what, when running with Valgrind, I am constantly running into memory leak errors with my DestructorHelper and most of the time my Insert.
Insert - inserting a node into the tree
bool BinTree::insert(NodeData* dataptr) {
Node* ptr = new Node; // exception is thrown if memory is not allocated
ptr->data = dataptr;
ptr->left = ptr->right = nullptr;
if (isEmpty()) {
root = ptr;
} else {
Node* current = root;
bool inserted = false;
// if item is less than current item, insert in left subtree,
// otherwise insert in right subtree
while (!inserted) {
if(*ptr->data == *current->data) {
delete ptr;
return false;
}
if (*ptr->data < *current->data) {
if (current->left == nullptr) { // at leaf, insert left
current->left = ptr;
inserted = true;
}
else
current = current->left; // one step left
}
else {
if (current->right == nullptr) { // at leaf, insert right
current->right = ptr;
inserted = true;
}
else
current = current->right; // one step right
}
}
}
return true;
}
DestructorHelper - called to delete the tree recursively
void BinTree::DestructorHelper(Node*& n) {
if(n) {
DestructorHelper(n->left);
DestructorHelper(n->right);
if(n->data) {
delete n->data;
}
delete n;
}
}
Valgrind Error
==20913== Invalid read of size 8
==20913== at 0x10AA4E: BinTree::insert(NodeData*) (in /home/UDRIVE/user/prog/a.out)
==20913== by 0x10A972: BinTree::TreeHelper(NodeData**, int, int) (in /home/UDRIVE/user/prog/a.out)
==20913== by 0x10A4CB: BinTree::arrayToBSTree(NodeData**) (in /home/UDRIVE/user/prog/a.out)
==20913== by 0x109C8A: main (in /home/UDRIVE/user/prog/a.out)
==20913== Address 0x5a883d0 is 0 bytes inside a block of size 24 free'd
==20913== at 0x4C2D2DB: operator delete(void*) (vg_replace_malloc.c:576)
==20913== by 0x10A70B: BinTree::DestructorHelper(BinTree::Node*&) (in /home/UDRIVE/user/prog/a.out)
==20913== by 0x10A268: BinTree::makeEmpty() (in /home/UDRIVE/user/prog/a.out)
==20913== by 0x10A45F: BinTree::bstreeToArray(NodeData**) (in /home/UDRIVE/user/prog/a.out)
==20913== by 0x109C71: main (in /home/UDRIVE/user/prog/a.out)
==20913== Block was alloc'd at
==20913== at 0x4C2C21F: operator new(unsigned long) (vg_replace_malloc.c:334)
==20913== by 0x10A9E5: BinTree::insert(NodeData*) (in /home/UDRIVE/user/prog/a.out)
==20913== by 0x10A085: buildTree(BinTree&, std::basic_ifstream<char, std::char_traits<char> >&) (in /home/UDRIVE/user/prog/a.out)
==20913== by 0x109812: main (in /home/UDRIVE/user/prog/a.out)
==20913==
==20913== Invalid read of size 8
==20913== at 0x4F55F00: std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::size() const (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.22)
==20913== by 0x10AF99: __gnu_cxx::__enable_if<std::__is_char<char>::__value, bool>::__type std::operator==<char>(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&) (in /home/UDRIVE/user/prog/a.out)
==20913== by 0x10ADA0: NodeData::operator==(NodeData const&) const (in /home/UDRIVE/user/prog/a.out)
==20913== by 0x10AA62: BinTree::insert(NodeData*) (in /home/UDRIVE/user/prog/a.out)
==20913== by 0x10A972: BinTree::TreeHelper(NodeData**, int, int) (in /home/UDRIVE/user/prog/a.out)
==20913== by 0x10A4CB: BinTree::arrayToBSTree(NodeData**) (in /home/UDRIVE/user/prog/a.out)
==20913== by 0x109C8A: main (in /home/UDRIVE/user/prog/a.out)
==20913== Address 0x8 is not stack'd, malloc'd or (recently) free'd
==20913==
==20913==
==20913== Process terminating with default action of signal 11 (SIGSEGV)
==20913== Access not within mapped region at address 0x8
==20913== at 0x4F55F00: std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::size() const (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.22)
==20913== by 0x10AF99: __gnu_cxx::__enable_if<std::__is_char<char>::__value, bool>::__type std::operator==<char>(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&) (in /home/UDRIVE/user/prog/a.out)
==20913== by 0x10ADA0: NodeData::operator==(NodeData const&) const (in /home/UDRIVE/user/prog/a.out)
==20913== by 0x10AA62: BinTree::insert(NodeData*) (in /home/UDRIVE/user/prog/a.out)
==20913== by 0x10A972: BinTree::TreeHelper(NodeData**, int, int) (in /home/UDRIVE/user/prog/a.out)
==20913== by 0x10A4CB: BinTree::arrayToBSTree(NodeData**) (in /home/UDRIVE/user/prog/a.out)
==20913== by 0x109C8A: main (in /home/UDRIVE/user/prog/a.out)
==20913== If you believe this happened as a result of a stack
==20913== overflow in your program's main thread (unlikely but
==20913== possible), you can try to increase the size of the
==20913== main thread stack using the --main-stacksize= flag.
==20913== The main thread stack size used in this run was 8388608.
==20913==
==20913== HEAP SUMMARY:
==20913== in use at exit: 10,928 bytes in 88 blocks
==20913== total heap usage: 120 allocs, 32 frees, 85,440 bytes allocated
==20913==
==20913== LEAK SUMMARY:
==20913== definitely lost: 48 bytes in 2 blocks
==20913== indirectly lost: 624 bytes in 26 blocks
==20913== possibly lost: 0 bytes in 0 blocks
==20913== still reachable: 10,256 bytes in 60 blocks
==20913== suppressed: 0 bytes in 0 blocks
==20913== Rerun with --leak-check=full to see details of leaked memory
==20913==
==20913== For counts of detected and suppressed errors, rerun with: -v
==20913== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
Segmentation fault
I have gone about looking online at other pieces of code but I can't seem to find anything that would hint at what I am missing.

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.

Memory leaks when Union was allocated memory using memset

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.

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.