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.
Related
I am trying to find a memory leak in my code but for the life of me, I cannot figure out or identify the reason for this leak. Which is why I am reaching out to your all. Thanks in advance.
The following code, creates a kerberos cache from keytab. The code is an extract of a bigger code, but this also has the same memory leak. The full code is as following
#include <iostream>
#include <cstring>
#include <krb5/krb5.h>
bool renew(krb5_context &_ctx, krb5_keytab &_keytab, krb5_ccache &_cache, std::string &_principal)
{
long int retval;
bool success = false;
krb5_principal principal;
krb5_creds *creds;
if ((retval = krb5_parse_name(_ctx, _principal.c_str(), &principal)))
throw "cannot parse principal string";
creds = (krb5_creds*) malloc(sizeof(*creds));
memset(creds, 0, sizeof(creds));
if ((retval = krb5_get_init_creds_keytab(_ctx, creds, principal, _keytab, 0, NULL, NULL)))
{
free(creds);
krb5_free_principal(_ctx, principal);
throw "cannot initialize keytab credentials - ";
}
if ((retval = krb5_cc_initialize(_ctx, _cache, principal)))
{
free(creds);
krb5_free_principal(_ctx, principal);
throw " cannot initialize cache - ";
}
if ((retval = krb5_cc_store_cred(_ctx, _cache, creds)))
{
free(creds);
krb5_free_principal(_ctx, principal);
throw "cannot store credentials - ";
}
free(creds);
krb5_free_principal(_ctx, principal);
return success;
}
int main()
{
long int retval;
std::string _keytab_file, _cache_file, _realm, _principal;
krb5_context _ctx = NULL;
krb5_keytab _keytab = NULL;
krb5_ccache _cache = NULL;
_keytab_file = "/location/to/the/keytab/file";
_cache_file = "/location/to/the/cache/file";
_principal = "user.name#DOMAIN.COM";
if ((retval = krb5_init_context(&_ctx)))
throw "cannot initialize context";
if ((retval = krb5_kt_resolve(_ctx, _keytab_file.c_str(), &_keytab)))
throw "cannot resolve keytab";
if ((retval = krb5_cc_resolve(_ctx, _cache_file.c_str(), &_cache)))
throw "cannot open/initialize kerberos cache";
try {
renew(_ctx, _keytab, _cache, _principal);
} catch (std::exception &e) {
std::cerr<<e.what()<<std::endl;
}
bailout:
if (_cache)
krb5_cc_close(_ctx, _cache);
if (_keytab)
krb5_kt_close(_ctx, _keytab);
if (_ctx)
krb5_free_context(_ctx);
return 0;
}
in a linux (or similar) box following used to compile and run with valgrind to check memory leak
g++ krb.cpp -o krb -lkrb5 -g
valgrind --leak-check=full ./krb
the valgrind report is as following-
==257623==
==257623== HEAP SUMMARY:
==257623== in use at exit: 4,964 bytes in 19 blocks
==257623== total heap usage: 9,165 allocs, 9,146 frees, 3,702,330 bytes allocated
==257623==
==257623== 16 bytes in 1 blocks are definitely lost in loss record 6 of 14
==257623== at 0x4C37135: malloc (vg_replace_malloc.c:381)
==257623== by 0x5E31F8D: krb5int_c_copy_keyblock_contents (in /usr/lib64/libk5crypto.so.3.1)
==257623== by 0x4E91146: ??? (in /usr/lib64/libkrb5.so.3.3)
==257623== by 0x4E9C65B: ??? (in /usr/lib64/libkrb5.so.3.3)
==257623== by 0x4E9C6F5: krb5_get_init_creds_keytab (in /usr/lib64/libkrb5.so.3.3)
==257623== by 0x4012EF: renew(_krb5_context*&, _krb5_kt*&, _krb5_ccache*&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&) (krb.cpp:25)
==257623== by 0x401612: main (krb.cpp:76)
==257623==
==257623== 78 (40 direct, 38 indirect) bytes in 1 blocks are definitely lost in loss record 8 of 14
==257623== at 0x4C37135: malloc (vg_replace_malloc.c:381)
==257623== by 0x4E91574: krb5_copy_principal (in /usr/lib64/libkrb5.so.3.3)
==257623== by 0x4E910EB: ??? (in /usr/lib64/libkrb5.so.3.3)
==257623== by 0x4E9C65B: ??? (in /usr/lib64/libkrb5.so.3.3)
==257623== by 0x4E9C6F5: krb5_get_init_creds_keytab (in /usr/lib64/libkrb5.so.3.3)
==257623== by 0x4012EF: renew(_krb5_context*&, _krb5_kt*&, _krb5_ccache*&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&) (krb.cpp:25)
==257623== by 0x401612: main (krb.cpp:76)
==257623==
==257623== 97 (40 direct, 57 indirect) bytes in 1 blocks are definitely lost in loss record 9 of 14
==257623== at 0x4C37135: malloc (vg_replace_malloc.c:381)
==257623== by 0x4E91574: krb5_copy_principal (in /usr/lib64/libkrb5.so.3.3)
==257623== by 0x4E9112F: ??? (in /usr/lib64/libkrb5.so.3.3)
==257623== by 0x4E9C65B: ??? (in /usr/lib64/libkrb5.so.3.3)
==257623== by 0x4E9C6F5: krb5_get_init_creds_keytab (in /usr/lib64/libkrb5.so.3.3)
==257623== by 0x4012EF: renew(_krb5_context*&, _krb5_kt*&, _krb5_ccache*&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&) (krb.cpp:25)
==257623== by 0x401612: main (krb.cpp:76)
==257623==
==257623== 1,646 bytes in 1 blocks are definitely lost in loss record 13 of 14
==257623== at 0x4C37135: malloc (vg_replace_malloc.c:381)
==257623== by 0x4E91369: krb5int_copy_data_contents (in /usr/lib64/libkrb5.so.3.3)
==257623== by 0x4E913EB: krb5_copy_data (in /usr/lib64/libkrb5.so.3.3)
==257623== by 0x4E91198: ??? (in /usr/lib64/libkrb5.so.3.3)
==257623== by 0x4E9C65B: ??? (in /usr/lib64/libkrb5.so.3.3)
==257623== by 0x4E9C6F5: krb5_get_init_creds_keytab (in /usr/lib64/libkrb5.so.3.3)
==257623== by 0x4012EF: renew(_krb5_context*&, _krb5_kt*&, _krb5_ccache*&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&) (krb.cpp:25)
==257623== by 0x401612: main (krb.cpp:76)
==257623==
==257623== LEAK SUMMARY:
==257623== definitely lost: 1,742 bytes in 4 blocks
==257623== indirectly lost: 95 bytes in 7 blocks
==257623== possibly lost: 0 bytes in 0 blocks
==257623== still reachable: 3,127 bytes in 8 blocks
==257623== suppressed: 0 bytes in 0 blocks
==257623== Reachable blocks (those to which a pointer was found) are not shown.
==257623== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==257623==
==257623== For lists of detected and suppressed errors, rerun with: -s
==257623== ERROR SUMMARY: 4 errors from 4 contexts (suppressed: 0 from 0)
looking forward to your input :)
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.
I am creating a linked list but I keep getting memory leaks. Sometimes it says the problem is in the at() function and sometimes in the remove() function, but it all looks pretty tight to me. What is causing memory leaks?
Here is my code for the linked list:
void LinkedList::insertHead(int value)
{
if (value < 0) {
return;
}
iterator pos(this, head);
for (int i = 0; i < num_items; i++) {
if (pos.current->data == value)
return;
else
pos++;
}
head = new Node(value, NULL, head);
if (head->next != NULL)
head->next->prev = head;
if (tail == NULL)
tail = head;
num_items++;
}
void LinkedList::insertTail(int value)
{
if (value < 0) {
return;
}
iterator pos(this, head);
for (int i = 0; i < num_items; i++) {
if (pos.current->data == value)
return;
else
pos++;
}
if (tail != NULL) {
tail->next = new Node(value, tail, NULL);
tail = tail->next;
num_items++;
} else
insertHead(value);
}
void LinkedList::insertAfter(int value, int insertionNode)
{
if (value < 0) {
return;
}
iterator pos(this, head);
for (int i = 0; i < num_items; i++) {
if (pos.current->data == value)
return;
else
pos++;
}
pos = iterator(this, head);
for (int i = 0; i < num_items; i++) {
if (pos.current->data == insertionNode)
break;
else
pos++;
}
if (pos.current == NULL || pos.current->data != insertionNode) {
return;
} /*else if(pos.current==NULL)
insertTail(value);*/
else {
Node *new_node = new Node(value, pos.current, pos.current->next);
if (pos.current->next != NULL)
pos.current->next->prev = new_node;
pos.current->next = new_node;
num_items++;
}
}
void LinkedList::remove(int value)
{
if (value < 0) {
return;
}
iterator pos(this, head);
for (int i = 0; i < num_items; i++) {
if (pos.current->data == value)
break;
else
pos++;
}
if (pos.current->data != value) {
return;
}
if (pos.current == head) {
Node *removed_node = head;
head = head->next;
delete removed_node;
if (head != NULL)
head->prev = NULL;
else
tail = NULL;
num_items--;
} else if (pos.current == tail) {
Node *removed_node = tail;
tail = tail->prev;
delete removed_node;
if (tail != NULL)
tail->next = NULL;
else
head = NULL;
num_items--;
} else {
Node *removed_node = pos.current;
removed_node->prev->next = removed_node->next;
removed_node->next->prev = removed_node->prev;
delete removed_node;
num_items--;
}
}
void LinkedList::clear()
{
if (num_items == 0)
return;
if (head != NULL)
remove(head->data);
num_items = 0;
}
int LinkedList::at(int index)
{
if (index < 0 || index >= num_items)
return -1;
iterator pos(this, head);
for (int i = 0; i < index; i++)
pos++;
return pos.current->data;
}
int LinkedList::size()
{
return num_items;
}
Here is code for the iterator:
class iterator {
friend class LinkedList;
private:
LinkedList * parent;
Node *current;
iterator(LinkedList * my_parent, Node * position):parent(my_parent),
current(position) {
}
public:
int &operator*() const {
if (current == NULL)
throw "Attempt to dereference end()";
return current->data;
}
int *operator->() const {
if (current == NULL)
throw "attempt to dereference end()";
return &(current->data);
}
iterator & operator++() {
if (current == NULL)
throw "Attempt to advance past end()";
current = current->next;
return *this;
}
iterator & operator--() {
if (current == parent->head)
throw "Attempt to move before begin()";
if (current == NULL)
current = parent->tail;
else
current = current->prev;
return *this;
}
iterator operator++(int) {
iterator return_value = *this;
++(*this);
return return_value;
}
iterator operator--(int) {
iterator return_value = *this;
--(*this);
return return_value;
}
bool operator==(const iterator & other) {
return current == other.current;
}
bool operator!=(const iterator & other) {
return !operator==(other);
}
};
output as requested:
==18072== Invalid read of size 4
==18072== at 0x402556: LinkedList::remove(int) (LinkedList.cpp:115)
==18072== by 0x405946: testAll() (in /users/guest/s/scalen/Desktop/To Students/dont_run_me)
==18072== by 0x401E81: main (in /users/guest/s/scalen/Desktop/To Students/dont_run_me)
==18072== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==18072==
segmentation fault
This segmentation fault was most likely caused by insertHead(), insertTail(), insertAfter(), or remove()
==18072==
==18072== HEAP SUMMARY:
==18072== in use at exit: 4,074 bytes in 118 blocks
==18072== total heap usage: 981 allocs, 863 frees, 158,945 bytes allocated
==18072==
==18072== 16 bytes in 1 blocks are still reachable in loss record 1 of 20
==18072== at 0x4A068F3: operator new(unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==18072== by 0x405888: testAll() (in /users/guest/s/scalen/Desktop/To Students/dont_run_me)
==18072== by 0x401E81: main (in /users/guest/s/scalen/Desktop/To Students/dont_run_me)
==18072==
==18072== 32 bytes in 1 blocks are still reachable in loss record 2 of 20
==18072== at 0x4A068F3: operator new(unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==18072== by 0x4020B2: Factory::getLinkedList() (Factory.cpp:21)
==18072== by 0x40587B: testAll() (in /users/guest/s/scalen/Desktop/To Students/dont_run_me)
==18072== by 0x401E81: main (in /users/guest/s/scalen/Desktop/To Students/dont_run_me)
==18072==
==18072== 32 bytes in 2 blocks are still reachable in loss record 3 of 20
==18072== at 0x4A068F3: operator new(unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==18072== by 0x407AC5: TADuck::insertHead(int) (in /users/guest/s/scalen/Desktop/To Students/dont_run_me)
==18072== by 0x405D91: testAll() (in /users/guest/s/scalen/Desktop/To Students/dont_run_me)
==18072== by 0x401E81: main (in /users/guest/s/scalen/Desktop/To Students/dont_run_me)
==18072==
==18072== 48 bytes in 2 blocks are still reachable in loss record 4 of 20
==18072== at 0x4A068F3: operator new(unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==18072== by 0x4021F1: LinkedList::insertHead(int) (LinkedList.cpp:20)
==18072== by 0x405D84: testAll() (in /users/guest/s/scalen/Desktop/To Students/dont_run_me)
==18072== by 0x401E81: main (in /users/guest/s/scalen/Desktop/To Students/dont_run_me)
==18072==
==18072== 48 bytes in 2 blocks are indirectly lost in loss record 5 of 20
==18072== at 0x4A068F3: operator new(unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==18072== by 0x40247A: LinkedList::insertAfter(int, int) (LinkedList.cpp:88)
==18072== by 0x405137: testAll() (in /users/guest/s/scalen/Desktop/To Students/dont_run_me)
==18072== by 0x401E81: main (in /users/guest/s/scalen/Desktop/To Students/dont_run_me)
==18072==
==18072== 192 bytes in 8 blocks are indirectly lost in loss record 6 of 20
==18072== at 0x4A068F3: operator new(unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==18072== by 0x402308: LinkedList::insertTail(int) (LinkedList.cpp:47)
==18072== by 0x404D9F: testAll() (in /users/guest/s/scalen/Desktop/To Students/dont_run_me)
==18072== by 0x401E81: main (in /users/guest/s/scalen/Desktop/To Students/dont_run_me)
==18072==
==18072== 216 bytes in 9 blocks are indirectly lost in loss record 7 of 20
==18072== at 0x4A068F3: operator new(unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==18072== by 0x4021F1: LinkedList::insertHead(int) (LinkedList.cpp:20)
==18072== by 0x404341: testAll() (in /users/guest/s/scalen/Desktop/To Students/dont_run_me)
==18072== by 0x401E81: main (in /users/guest/s/scalen/Desktop/To Students/dont_run_me)
==18072==
==18072== 216 bytes in 9 blocks are indirectly lost in loss record 8 of 20
==18072== at 0x4A068F3: operator new(unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==18072== by 0x4021F1: LinkedList::insertHead(int) (LinkedList.cpp:20)
==18072== by 0x404BAD: testAll() (in /users/guest/s/scalen/Desktop/To Students/dont_run_me)
==18072== by 0x401E81: main (in /users/guest/s/scalen/Desktop/To Students/dont_run_me)
==18072==
==18072== 240 bytes in 10 blocks are indirectly lost in loss record 9 of 20
==18072== at 0x4A068F3: operator new(unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==18072== by 0x402308: LinkedList::insertTail(int) (LinkedList.cpp:47)
==18072== by 0x4046B1: testAll() (in /users/guest/s/scalen/Desktop/To Students/dont_run_me)
==18072== by 0x401E81: main (in /users/guest/s/scalen/Desktop/To Students/dont_run_me)
==18072==
==18072== 240 bytes in 10 blocks are indirectly lost in loss record 10 of 20
==18072== at 0x4A068F3: operator new(unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==18072== by 0x40247A: LinkedList::insertAfter(int, int) (LinkedList.cpp:88)
==18072== by 0x404897: testAll() (in /users/guest/s/scalen/Desktop/To Students/dont_run_me)
==18072== by 0x401E81: main (in /users/guest/s/scalen/Desktop/To Students/dont_run_me)
==18072==
==18072== 256 bytes in 1 blocks are still reachable in loss record 11 of 20
==18072== at 0x4A068F3: operator new(unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==18072== by 0x4074AD: std::vector<int, std::allocator<int> >::_M_insert_aux(__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, int const&) (in /users/guest/s/scalen/Desktop/To Students/dont_run_me)
==18072== by 0x402B7C: fillMasterList(std::vector<int, std::allocator<int> >&, int) (in /users/guest/s/scalen/Desktop/To Students/dont_run_me)
==18072== by 0x404B82: testAll() (in /users/guest/s/scalen/Desktop/To Students/dont_run_me)
==18072== by 0x401E81: main (in /users/guest/s/scalen/Desktop/To Students/dont_run_me)
==18072==
==18072== 432 bytes in 18 blocks are indirectly lost in loss record 12 of 20
==18072== at 0x4A068F3: operator new(unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==18072== by 0x4021F1: LinkedList::insertHead(int) (LinkedList.cpp:20)
==18072== by 0x402BFD: initList(LinkedListInterface*, LinkedListInterface*) (in /users/guest/s/scalen/Desktop/To Students/dont_run_me)
==18072== by 0x403F78: testAll() (in /users/guest/s/scalen/Desktop/To Students/dont_run_me)
==18072== by 0x401E81: main (in /users/guest/s/scalen/Desktop/To Students/dont_run_me)
==18072==
==18072== 456 bytes in 19 blocks are indirectly lost in loss record 13 of 20
==18072== at 0x4A068F3: operator new(unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==18072== by 0x4021F1: LinkedList::insertHead(int) (LinkedList.cpp:20)
==18072== by 0x4039E9: testAll() (in /users/guest/s/scalen/Desktop/To Students/dont_run_me)
==18072== by 0x401E81: main (in /users/guest/s/scalen/Desktop/To Students/dont_run_me)
==18072==
==18072== 480 bytes in 20 blocks are indirectly lost in loss record 14 of 20
==18072== at 0x4A068F3: operator new(unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==18072== by 0x4021F1: LinkedList::insertHead(int) (LinkedList.cpp:20)
==18072== by 0x402BFD: initList(LinkedListInterface*, LinkedListInterface*) (in /users/guest/s/scalen/Desktop/To Students/dont_run_me)
==18072== by 0x4040DF: testAll() (in /users/guest/s/scalen/Desktop/To Students/dont_run_me)
==18072== by 0x401E81: main (in /users/guest/s/scalen/Desktop/To Students/dont_run_me)
==18072==
==18072== 480 (24 direct, 456 indirect) bytes in 1 blocks are definitely lost in loss record 15 of 20
==18072== at 0x4A068F3: operator new(unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==18072== by 0x4021F1: LinkedList::insertHead(int) (LinkedList.cpp:20)
==18072== by 0x4039E9: testAll() (in /users/guest/s/scalen/Desktop/To Students/dont_run_me)
==18072== by 0x401E81: main (in /users/guest/s/scalen/Desktop/To Students/dont_run_me)
==18072==
==18072== 480 (24 direct, 456 indirect) bytes in 1 blocks are definitely lost in loss record 16 of 20
==18072== at 0x4A068F3: operator new(unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==18072== by 0x4021F1: LinkedList::insertHead(int) (LinkedList.cpp:20)
==18072== by 0x402374: LinkedList::insertTail(int) (LinkedList.cpp:52)
==18072== by 0x404D9F: testAll() (in /users/guest/s/scalen/Desktop/To Students/dont_run_me)
==18072== by 0x401E81: main (in /users/guest/s/scalen/Desktop/To Students/dont_run_me)
==18072==
==18072== 537 bytes in 1 blocks are possibly lost in loss record 17 of 20
==18072== at 0x4A068F3: operator new(unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==18072== by 0x38C88B9F48: std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) (in /usr/lib64/libstdc++.so.6.0.18)
==18072== by 0x38C88BAB1A: std::string::_Rep::_M_clone(std::allocator<char> const&, unsigned long) (in /usr/lib64/libstdc++.so.6.0.18)
==18072== by 0x38C88BABB3: std::string::reserve(unsigned long) (in /usr/lib64/libstdc++.so.6.0.18)
==18072== by 0x38C8898F75: std::basic_stringbuf<char, std::char_traits<char>, std::allocator<char> >::overflow(int) (in /usr/lib64/libstdc++.so.6.0.18)
==18072== by 0x38C889D195: std::basic_streambuf<char, std::char_traits<char> >::xsputn(char const*, long) (in /usr/lib64/libstdc++.so.6.0.18)
==18072== by 0x38C88949A4: 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/lib64/libstdc++.so.6.0.18)
==18072== by 0x4036B6: testAll() (in /users/guest/s/scalen/Desktop/To Students/dont_run_me)
==18072== by 0x401E81: main (in /users/guest/s/scalen/Desktop/To Students/dont_run_me)
==18072==
==18072== 537 bytes in 1 blocks are possibly lost in loss record 18 of 20
==18072== at 0x4A068F3: operator new(unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==18072== by 0x38C88B9F48: std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) (in /usr/lib64/libstdc++.so.6.0.18)
==18072== by 0x38C88BAB1A: std::string::_Rep::_M_clone(std::allocator<char> const&, unsigned long) (in /usr/lib64/libstdc++.so.6.0.18)
==18072== by 0x38C88BABB3: std::string::reserve(unsigned long) (in /usr/lib64/libstdc++.so.6.0.18)
==18072== by 0x38C8898F75: std::basic_stringbuf<char, std::char_traits<char>, std::allocator<char> >::overflow(int) (in /usr/lib64/libstdc++.so.6.0.18)
==18072== by 0x38C889D195: std::basic_streambuf<char, std::char_traits<char> >::xsputn(char const*, long) (in /usr/lib64/libstdc++.so.6.0.18)
==18072== by 0x38C88949A4: 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/lib64/libstdc++.so.6.0.18)
==18072== by 0x403A7C: testAll() (in /users/guest/s/scalen/Desktop/To Students/dont_run_me)
==18072== by 0x401E81: main (in /users/guest/s/scalen/Desktop/To Students/dont_run_me)
==18072==
==18072== 720 (24 direct, 696 indirect) bytes in 1 blocks are definitely lost in loss record 19 of 20
==18072== at 0x4A068F3: operator new(unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==18072== by 0x4021F1: LinkedList::insertHead(int) (LinkedList.cpp:20)
==18072== by 0x404341: testAll() (in /users/guest/s/scalen/Desktop/To Students/dont_run_me)
==18072== by 0x401E81: main (in /users/guest/s/scalen/Desktop/To Students/dont_run_me)
==18072==
==18072== 936 (24 direct, 912 indirect) bytes in 1 blocks are definitely lost in loss record 20 of 20
==18072== at 0x4A068F3: operator new(unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==18072== by 0x4021F1: LinkedList::insertHead(int) (LinkedList.cpp:20)
==18072== by 0x402BFD: initList(LinkedListInterface*, LinkedListInterface*) (in /users/guest/s/scalen/Desktop/To Students/dont_run_me)
==18072== by 0x403F78: testAll() (in /users/guest/s/scalen/Desktop/To Students/dont_run_me)
==18072== by 0x401E81: main (in /users/guest/s/scalen/Desktop/To Students/dont_run_me)
==18072==
==18072== LEAK SUMMARY:
==18072== definitely lost: 96 bytes in 4 blocks
==18072== indirectly lost: 2,520 bytes in 105 blocks
==18072== possibly lost: 1,074 bytes in 2 blocks
==18072== still reachable: 384 bytes in 7 blocks
==18072== suppressed: 0 bytes in 0 blocks
==18072==
==18072== For counts of detected and suppressed errors, rerun with: -v
==18072== ERROR SUMMARY: 7 errors from 7 contexts (suppressed: 2 from 2)
Your valgrind output is reporting memory leaks. However, those can be ignored for now because your program suffered a segmentation fault as a result of an invalid read on memory location 0x0:
==18072== Invalid read of size 4
==18072== at 0x402556: LinkedList::remove(int) (LinkedList.cpp:115)
==18072== by 0x405946: testAll() (in /users/guest/s/scalen/Desktop/To Students/dont_run_me)
==18072== by 0x401E81: main (in /users/guest/s/scalen/Desktop/To Students/dont_run_me)
==18072== Address 0x0 is not stack'd, malloc'd or (recently) free'd
segmentation fault
You need to find where line 115 is and figure out why the code is trying to deference an invalid memory location. As an example, I will illustrate with the first one I found (I don't know if this is the one that valgrind is complaining about or not, since I do not know what the line numbers are for your code):
for (int i = 0; i < num_items; i++) {
if (pos.current->data == value)
break;
else
pos++;
}
if (pos.current->data != value) {
return;
}
In the case that there is no match for value, it seems unlikely that pos.current will point to a meaningful entry. So dereferencing it to check if it doesn't match for the early return is probably the wrong thing to do. Instead, check if the for loop actually made it through the entire list:
int i;
for (i = 0; i < num_items; i++) {
//...
}
if (i == num_items) {
return;
}
As you encounter the errors reported in valgrind, address the segmentation faults first, then the Invalid reads or Invalid writes, then the memory leaks.
From your comment, you seemed a little stumped on the process of debugging. This question was about memory leaks, but that turned out to be a symptom of a crash. Hopefully, this answer has helped you to understand a bit better how to understand the output that valgrind reports, but you should spend some time going over its documentation so that you are able to extract the maximum amount of information from it that you can. To that end, your issue has been addressed. However, let me expand this answer slightly to discuss a little bit about debugging.
Debugging is simply a problem solving exercise, and being good at it is a skill. It is a process that can be likened to solving a crime or a mystery, so debugging is when a programmer gets to be the detective. As with most human endeavors, there are people who are much better at debugging than others. But anyone can become a skillful debugger, because it is also true that you can become better a debugging with practice.
I studied a lot of math during high school and college, so I am biased in the belief that debugging is very similar to solving a mathematical problem. With time, you gain an intuition as to how to drive yourself to the solution more quickly, but at a high level, the process I take largely follows the steps laid out by George Polya in his book How to Solve It.
First: Understand the problem. What is the input? What is the output? What output is the program expected to produce? What assumptions and preconditions are required by your program? Have all those conditions been satisfied?
Second: Devise a plan. Is the problem new or is it similar to a problem you have faced in the past? Is there a relationship between the aberrant result and a particular part of your program? What assumptions and preconditions are required by that part of your program for it to behave correctly? Are you able to test those conditions?
Third: Carry out the plan. If the problem is not new, resolve the issue by applying a fix similar to what you had done before if possible. Otherwise, inspect the state of the program step by step to make sure all the assumptions and preconditions are being satisfied. Determine at what point the program behavior deviate from what it should have done. At the point of deviation, understand the cause of the deviation, and take the appropriate corrective action.
Fourth: Looking back. After the program has been corrected, take the steps needed to convince yourself that the fix is correct. Whatever tests that had passed in the past should still pass. Whatever test had caused the failure should now pass. Identify new tests that may expose other weaknesses in that part of the code. Understand why the problem was introduced, and think of ways that you can change how you write programs in the future that will either make it less likely to make the same error, or make the cause of the problem easier to identify.
In this code segment from remove,
iterator pos(this, head);
for (int i = 0; i < num_items; i++) {
if (pos.current->data == value)
break;
else
pos++;
}
if (pos.current->data != value) {
return;
}
you advance pos to the very end of your list (if value is not found, at least), so might pos.current be NULL when you try to access pos.current->data afterwards?
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?
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.