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 :)
Related
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.
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.
Here is my very simple code:
#include <opencv/highgui.h>
#include <opencv/cv.h>
#include <iostream>
using namespace std;
using namespace cv;
int main(int argc, char** argv)
{
for(int i=0;i<2;i++){
ostringstream tmp;
tmp << "/vol/test1/" << i << ".jpg";
IplImage * img = cvLoadImage(tmp.str().c_str()); //line #12
IplImage* imgc = cvCreateImage(cvGetSize(img), img->depth,3);
cvCvtColor(img, imgc, CV_BGR2Lab); //line #14
cvReleaseImage(&img);
img = imgc;
cvReleaseImage(&img);
}
return 0;
}
The program just loads 2 images, and transforms them to CIELab space. However, Valgrind throws the following errors:
==31879== LEAK SUMMARY:
==31879== definitely lost: 0 bytes in 0 blocks
==31879== indirectly lost: 0 bytes in 0 blocks
==31879== possibly lost: 0 bytes in 0 blocks
==31879== still reachable: 14,456 bytes in 6 blocks
==31879== suppressed: 0 bytes in 0 blocks
==31879==
==31879== ERROR SUMMARY: 903892 errors from 3 contexts (suppressed: 2 from 2)
Further check with -g --show-reachable=yes gives me the details of the leak (the reports for block 1-4 are as the same as block 5 so I do not post it here):
==31879== 2,072 bytes in 1 blocks are still reachable in loss record 5 of 6
==31879== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==31879== by 0x10B3DF5A: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
==31879== by 0x10B40D3F: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
==31879== by 0x10B03A68: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
==31879== by 0x400F305: call_init.part.0 (dl-init.c:85)
==31879== by 0x400F3DE: _dl_init (dl-init.c:52)
==31879== by 0x40016E9: ??? (in /lib/x86_64-linux-gnu/ld-2.15.so)
==31879==
==31879== 4,096 bytes in 1 blocks are still reachable in loss record 6 of 6
==31879== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==31879== by 0x64870B7: libjpeg_general_init (in /usr/lib/x86_64-linux-gnu/libjpeg.so.8.0.2)
==31879== by 0x400F305: call_init.part.0 (dl-init.c:85)
==31879== by 0x400F3DE: _dl_init (dl-init.c:52)
==31879== by 0x40016E9: ??? (in /lib/x86_64-linux-gnu/ld-2.15.so)
Since the memory leak is "still reachable", I think I can safely ignore it. But it is the Error Summary of 903892 errors that concerns me. I rerun valgrind with --track-origins=yes:
==31879== ERROR SUMMARY: 903892 errors from 3 contexts (suppressed: 2 from 2)
==31879==
==31879== 301229 errors in context 1 of 3:
==31879== Use of uninitialised value of size 8
==31879== at 0x55219F0: cv::CvtColorLoop_Invoker<cv::RGB2Lab_b>::operator()(cv::Range const&) const (in /vol/Toolkits/opencv-2.4.10/release/lib/libopencv_imgproc.so.2.4.10)
==31879== by 0x5536152: cv::cvtColor(cv::_InputArray const&, cv::_OutputArray const&, int, int) (in /vol/Toolkits/opencv-2.4.10/release/lib/libopencv_imgproc.so.2.4.10)
==31879== by 0x55403A8: cvCvtColor (in /vol/Toolkits/opencv-2.4.10/release/lib/libopencv_imgproc.so.2.4.10)
==31879== by 0x400DEB: main (main.cpp:14)
==31879== Uninitialised value was created by a heap allocation
==31879== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==31879== by 0x64ABA74: ??? (in /usr/lib/x86_64-linux-gnu/libjpeg.so.8.0.2)
==31879== by 0x64ABD02: ??? (in /usr/lib/x86_64-linux-gnu/libjpeg.so.8.0.2)
==31879== by 0x649EFF9: jinit_d_main_controller (in /usr/lib/x86_64-linux-gnu/libjpeg.so.8.0.2)
==31879== by 0x64A22BB: jinit_master_decompress (in /usr/lib/x86_64-linux-gnu/libjpeg.so.8.0.2)
==31879== by 0x64991D4: jpeg_start_decompress (in /usr/lib/x86_64-linux-gnu/libjpeg.so.8.0.2)
==31879== by 0x4E64621: cv::JpegDecoder::readData(cv::Mat&) (in /vol/Toolkits/opencv-2.4.10/release/lib/libopencv_highgui.so.2.4.10)
==31879== by 0x4E4AC8C: cv::imread_(std::string const&, int, int, cv::Mat*) (in /vol/Toolkits/opencv-2.4.10/release/lib/libopencv_highgui.so.2.4.10)
==31879== by 0x4E4B13B: cvLoadImage (in /vol/Toolkits/opencv-2.4.10/release/lib/libopencv_highgui.so.2.4.10)
==31879== by 0x400D9D: main (main.cpp:12)
(The reports for context 2 and 3 are as the same as context 1 so I do not post it here). The errors seem come from line 12 and 14 in my code. What is wrong? or Am I missing something here?
Side note: if I scan more images, the report for leak memory is the same, but number of errors in Error Summary increases linearly. My program runs to segmentation fault after scanning ~3000 images.
please, avoid all deprecated IplImages, and use cv::Mat, and the c++ api instead.
#include <opencv2/opencv.hpp> // c++ headers
#include <iostream>
using namespace std;
using namespace cv;
int main(int argc, char** argv)
{
for(int i=0;i<2;i++){
ostringstream tmp;
tmp << "/vol/test1/" << i << ".jpg";
Mat img = imread(tmp.str().c_str());
Mat imgc; // no pre-allocation nessecary
cvtColor(img, imgc, CV_BGR2Lab);
// no manual release nessecary
}
return 0;
}
I have implemented multitask application in c++. Producer push on queue, and consumer get elements from queue. Sometimes my application crashed. Could someone help me with this problem. sf
Valgrind output:
==10769== Memcheck, a memory error detector
==10769== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==10769== Using Valgrind-3.9.0 and LibVEX; rerun with -h for copyright info
==10769== Command: ./tachyon -s /HOME_ann/BII/biidurgak/test_new_tachyon/Tachyon_v5_improvedQueryTime/settings_smallNR
==10769==
==10769== Thread 5:
==10769== Invalid read of size 4
==10769== at 0x342669C9DE: std::string::assign(std::string const&) (in /usr/lib64/libstdc++.so.6.0.8)
==10769== by 0x42E01A: std::pair::operator=(std::pair const&) (stl_pair.h:152)
==10769== by 0x42B27A: boost::lockfree::detail::ringbuffer_base >::pop(std::pair&, std::pair*, unsigned
long) (spsc_queue.hpp:154)
==10769== by 0x428719: boost::lockfree::detail::compile_time_sized_ringbuffer, 2ul>::pop(std::pair&) (spsc_queue.hpp:305)
==10769== by 0x425DEA: boost::lockfree::spsc_queue, boost::lockfree::capacity, boost::parameter::void_>::pop(std::pair&) (spsc_queue.hpp:572)
==10769== by 0x41BE16: findInDatabase() (Tachyon.cpp:103)
==10769== by 0x4351D4: boost::detail::thread_data::run() (thread.hpp:117)
==10769== by 0x4E53D01: thread_proxy (in /HOME_ann/BII/biidurgak/test_new_tachyon/boost_install/boost_1_55_0/lib/libboost_thread.so.1.55.0)
==10769== by 0x342120673C: start_thread (in /lib64/libpthread-2.5.so)
==10769== by 0x34206D3D1C: clone (in /lib64/libc-2.5.so)
==10769== Address 0xfffffffffffffff8 is not stack'd, malloc'd or (recently) free'd
==10769==
==10769==
==10769== Process terminating with default action of signal 11 (SIGSEGV)
==10769== Access not within mapped region at address 0xFFFFFFFFFFFFFFF8
==10769== at 0x342669C9DE: std::string::assign(std::string const&) (in /usr/lib64/libstdc++.so.6.0.8)
==10769== by 0x42E01A: std::pair::operator=(std::pair const&) (stl_pair.h:152)
==10769== by 0x42B27A: boost::lockfree::detail::ringbuffer_base >::pop(std::pair&, std::pair*, unsigned long) (spsc_queue.hpp:154)
==10769== by 0x428719: boost::lockfree::detail::compile_time_sized_ringbuffer, 2ul>::pop(std::pair&) (spsc_queue.hpp:305)
==10769== by 0x425DEA: boost::lockfree::spsc_queue, boost::lockfree::capacity, boost::parameter::void_>::pop(std::pair&) (spsc_queue.hpp:572)
==10769== by 0x41BE16: findInDatabase() (Tachyon.cpp:103)
==10769== by 0x4351D4: boost::detail::thread_data::run() (thread.hpp:117)
==10769== by 0x4E53D01: thread_proxy (in /HOME_ann/BII/biidurgak/test_new_tachyon/boost_install/boost_1_55_0/lib/libboost_thread.so.1.55.0)
==10769== by 0x342120673C: start_thread (in /lib64/libpthread-2.5.so)
==10769== by 0x34206D3D1C: clone (in /lib64/libc-2.5.so)
==10769== If you believe this happened as a result of a stack
==10769== overflow in your program's main thread (unlikely but
==10769== possible), you can try to increase the size of the
==10769== main thread stack using the --main-stacksize= flag.
==10769== The main thread stack size used in this run was 10485760.
==10769==
==10769== HEAP SUMMARY:
==10769== in use at exit: 219,895,341 bytes in 4,598,508 blocks
==10769== total heap usage: 36,680,650 allocs, 32,082,142 frees, 1,474,244,383 bytes allocated
==10769==
==10769== LEAK SUMMARY:
==10769== definitely lost: 1,904 bytes in 2 blocks
==10769== indirectly lost: 0 bytes in 0 blocks
==10769== possibly lost: 184,232,229 bytes in 4,598,462 blocks
==10769== still reachable: 35,661,208 bytes in 44 blocks
==10769== suppressed: 0 bytes in 0 blocks
==10769== Rerun with --leak-check=full to see details of leaked memory
==10769==
==10769== For counts of detected and suppressed errors, rerun with: -v
Producer:
void producer(string file) {
ifstream query(file.c_str());
string description = "";
string sequence = "";
string line;
while (getline(query, line)) {
//read description
if (line == "") continue;
if (line.at(0) == '>') {
if (sequence != "") {
pair<string, string> a = make_pair(description, sequence);
while (!queue.push(a))
;
sequence = "";
}
description = line.substr(1);
} else {
sequence += line;
}
}
if (sequence != "" && description != "") {
pair<string, string> a = make_pair(description, sequence);
while (!queue.push(a))
;
}
}
In the consumer I have this:
void Consumer(void) {
pair<string, string>element;
//part of code
while(queue.pop(element)){ //Line 103 in Tachyon.cpp
string queryDescription = element.first;
string sequence = element.second;
//Part of code
}
}
Queue is the global variable:
boost::lockfree::spsc_queue<pair<string, string>, boost::lockfree::capacity<2> > queue;
Global variables, multiple threads (I assume), one reading and another thread writing - you need a synchronization object like mutex or critical section.
Pseudocode:
// Consumer
loop-begin;
Lock();
get-item-into-local-variable
Unlock();
process-local-variable-item;
loop-end
// Producer
void AddItem(item)
{
Lock();
Add-item-into-queue
Unlock();
}
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?