From: Simon W. <si...@gi...> - 2012-06-06 05:44:30
Attachments:
ptr.log
unique.log
|
Hi, I have here a very simple test program that crashes with a SIGSEGV. When running it through valgrind, it shows memory leaks. I've written this piece of code as I am having trouble with a larger project. However, I think I've isolated it to libodbc++ or unixodbc. I initially used std::unique_ptr. But thought I'd try plain old pointers for this test. Either way, there are probelms. Here is the program: --------------------------------------- #include <string> #include <sstream> #include <iostream> #include <odbc++/drivermanager.h> #include <odbc++/connection.h> #include <odbc++/preparedstatement.h> #include <odbc++/callablestatement.h> #include <odbc++/resultset.h> #include <odbc++/databasemetadata.h> #include <odbc++/resultsetmetadata.h> int main(int argc, char** argv) { int test; std::string dbConnectString = "DSN=agentportal;USER=xxx;PASSWORD=xxx"; std::stringstream query; query << "select sleep(" << 30 << "), 1 as test"; try { odbc::Connection* connection = odbc::DriverManager::getConnection(dbConnectString); odbc::Statement* statement = connection->createStatement(); odbc::ResultSet* resultSet = statement->executeQuery(query.str()); while (resultSet->next()) { test = resultSet->getInt("test"); } delete connection; delete statement; delete resultSet; } catch(odbc::SQLException& e) { std::cout << std::endl << "error code: "<< e.getErrorCode() << std::endl << "error message: " << e.getMessage() << std::endl; } return 0; } --------------------------------------- #include <string> #include <sstream> #include <iostream> #include <memory> #include <odbc++/drivermanager.h> #include <odbc++/connection.h> #include <odbc++/preparedstatement.h> #include <odbc++/callablestatement.h> #include <odbc++/resultset.h> #include <odbc++/databasemetadata.h> #include <odbc++/resultsetmetadata.h> int main(int argc, char** argv) { int test; std::string dbConnectString = "DSN=agentportal;USER=xxx;PASSWORD=xxx"; std::stringstream query; query << "select 1 as test"; try { std::unique_ptr<odbc::Connection> connection (odbc::DriverManager::getConnection(dbConnectString)); std::unique_ptr<odbc::Statement> statement (connection->createStatement()); std::unique_ptr<odbc::ResultSet> resultSet (statement->executeQuery(query.str())); while (resultSet->next()) { test = resultSet->getInt("test"); } std::cout << test << std::endl; } catch(odbc::SQLException& e) { std::cout << std::endl << "error code: "<< e.getErrorCode() << std::endl << "error message: " << e.getMessage() << std::endl; } return 0; } --------------------------------------- (gdb) r Starting program: /home/weelz/htserve/trunk/testODBC [Thread debugging using libthread_db enabled] [New Thread 0xb799cb70 (LWP 7865)] [Thread 0xb799cb70 (LWP 7865) exited] Program received signal SIGSEGV, Segmentation fault. 0x00000489 in ?? () (gdb) bt #0 0x00000489 in ?? () #1 0xb7d18ca6 in __libc_start_main (main=0x8048e64 <main>, argc=1, ubp_av=0xbffff7a4, init=0x8049230 <__libc_csu_init>, fini=0x8049220 <__libc_csu_fini>, rtld_fini=0xb7ff1380 <_dl_fini>, stack_end=0xbffff79c) at libc-start.c:228 #2 0x08048dd1 in _start () (gdb) --------------------------------------- I've attached the valgrind output as it is rather long. prt.log is for the plain pointer version up top. unique.log is for the version that uses unique_ptr. Admittedly, the unique_ptr behaves better, but still has issues. I suspect I am doing something wrong when compiling libodbc++ rather than there is a bug. I see the similar behavior with TDS as well. Short of building everything from source (gentoo?), I thought I'd see if anyone has any ideas on what could be the problem. Has anyone run into similar issues? Thanks, Simon -- simonsmicrophone.com |
From: Pete <pe...@ka...> - 2012-06-06 10:45:10
|
Further to Jan's suggestions, unless you do: odbc::DriverManager::shutdown(); before exiting from your program you'll get leaks. Pete > -----Original Message----- > From: Simon Walter [mailto:si...@gi...] > Sent: Wednesday, 6 June 2012 5:45 p.m. > To: lib...@li... > Subject: [libodbcxx-devel] segmentation fault help please > > Hi, > > I have here a very simple test program that crashes with a > SIGSEGV. When running it through valgrind, it shows memory leaks. > > I've written this piece of code as I am having trouble with a > larger project. However, I think I've isolated it to > libodbc++ or unixodbc. > > I initially used std::unique_ptr. But thought I'd try plain > old pointers for this test. Either way, there are probelms. > > Here is the program: > --------------------------------------- > #include <string> > #include <sstream> > #include <iostream> > #include <odbc++/drivermanager.h> > #include <odbc++/connection.h> > #include <odbc++/preparedstatement.h> > #include <odbc++/callablestatement.h> > #include <odbc++/resultset.h> > #include <odbc++/databasemetadata.h> > #include <odbc++/resultsetmetadata.h> > > > int main(int argc, char** argv) > { > int test; > std::string dbConnectString = > "DSN=agentportal;USER=xxx;PASSWORD=xxx"; > std::stringstream query; > query << "select sleep(" << 30 << "), 1 as test"; > > try > { > odbc::Connection* connection = > odbc::DriverManager::getConnection(dbConnectString); > odbc::Statement* statement = connection->createStatement(); > odbc::ResultSet* resultSet = > statement->executeQuery(query.str()); > > while (resultSet->next()) > { > test = resultSet->getInt("test"); > } > > delete connection; > delete statement; > delete resultSet; > } > catch(odbc::SQLException& e) > { > std::cout << std::endl << "error code: "<< > e.getErrorCode() << std::endl << "error message: " << > e.getMessage() << std::endl; > } > > return 0; > } > --------------------------------------- > #include <string> > #include <sstream> > #include <iostream> > #include <memory> > #include <odbc++/drivermanager.h> > #include <odbc++/connection.h> > #include <odbc++/preparedstatement.h> > #include <odbc++/callablestatement.h> > #include <odbc++/resultset.h> > #include <odbc++/databasemetadata.h> > #include <odbc++/resultsetmetadata.h> > > > int main(int argc, char** argv) > { > int test; > std::string dbConnectString = > "DSN=agentportal;USER=xxx;PASSWORD=xxx"; > std::stringstream query; > query << "select 1 as test"; > > try > { > std::unique_ptr<odbc::Connection> connection > (odbc::DriverManager::getConnection(dbConnectString)); > std::unique_ptr<odbc::Statement> statement > (connection->createStatement()); > std::unique_ptr<odbc::ResultSet> resultSet > (statement->executeQuery(query.str())); > > while (resultSet->next()) > { > test = resultSet->getInt("test"); > } > std::cout << test << std::endl; > } > catch(odbc::SQLException& e) > { > std::cout << std::endl << "error code: "<< > e.getErrorCode() << std::endl << "error message: " << > e.getMessage() << std::endl; > } > > return 0; > } > --------------------------------------- > (gdb) r > Starting program: /home/weelz/htserve/trunk/testODBC > [Thread debugging using libthread_db enabled] [New Thread > 0xb799cb70 (LWP 7865)] [Thread 0xb799cb70 (LWP 7865) exited] > > Program received signal SIGSEGV, Segmentation fault. > 0x00000489 in ?? () > (gdb) bt > #0 0x00000489 in ?? () > #1 0xb7d18ca6 in __libc_start_main (main=0x8048e64 <main>, > argc=1, ubp_av=0xbffff7a4, init=0x8049230 <__libc_csu_init>, > fini=0x8049220 <__libc_csu_fini>, rtld_fini=0xb7ff1380 > <_dl_fini>, stack_end=0xbffff79c) > at libc-start.c:228 > #2 0x08048dd1 in _start () > (gdb) > --------------------------------------- > I've attached the valgrind output as it is rather long. > prt.log is for the plain pointer version up top. unique.log > is for the version that uses unique_ptr. Admittedly, the > unique_ptr behaves better, but still has issues. > > I suspect I am doing something wrong when compiling libodbc++ > rather than there is a bug. I see the similar behavior with > TDS as well. > > Short of building everything from source (gentoo?), I thought > I'd see if anyone has any ideas on what could be the problem. > > Has anyone run into similar issues? > > Thanks, > > Simon > > -- > simonsmicrophone.com > |
From: Simon W. <si...@gi...> - 2012-06-07 01:09:34
|
On 06/06/2012 07:27 PM, Pete wrote: > > Further to Jan's suggestions, unless you do: > > odbc::DriverManager::shutdown(); > > before exiting from your program you'll get leaks. > Thanks for that Pete and Jan. I got this error upon exit: error code: 0 error message: Failed to shutdown DriverManager: [unixODBC][Driver Manager]Function sequence error As I'd gone back to using unique_ptr, I figured I should reset() them in the order Jan specified - which makes sense. But there is still a memory leak. Is this to be expected? Am I looking at something to do with the ODBC libs? $ valgrind --tool=memcheck --leak-check=full ./testODBCtds ==14771== Memcheck, a memory error detector ==14771== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al. ==14771== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info ==14771== Command: ./testODBCtds ==14771== 1 ==14771== ==14771== HEAP SUMMARY: ==14771== in use at exit: 5,192 bytes in 201 blocks ==14771== total heap usage: 1,788 allocs, 1,587 frees, 1,455,615 bytes allocated ==14771== ==14771== 160 (40 direct, 120 indirect) bytes in 1 blocks are definitely lost in loss record 192 of 195 ==14771== at 0x4023F50: malloc (vg_replace_malloc.c:236) ==14771== by 0x429C1E3: nss_parse_service_list (nsswitch.c:622) ==14771== by 0x429C926: __nss_database_lookup (nsswitch.c:164) ==14771== by 0x402AEAB: ??? ==14771== by 0x402BB6C: ??? ==14771== by 0x4255994: getpwuid_r@@GLIBC_2.1.2 (getXXbyYY_r.c:253) ==14771== by 0x42552FE: getpwuid (getXXbyYY.c:117) ==14771== by 0x4378920: ??? (in /usr/lib/libodbc.so.1.0.0) ==14771== by 0x4375445: ??? (in /usr/lib/libodbc.so.1.0.0) ==14771== by 0x43617FF: ??? (in /usr/lib/libodbc.so.1.0.0) ==14771== by 0x43330E2: SQLDriverConnect (in /usr/lib/libodbc.so.1.0.0) ==14771== by 0x40493FE: odbc::Connection::_connect(std::string const&, unsigned short) (connection.cpp:227) ==14771== ==14771== LEAK SUMMARY: ==14771== definitely lost: 40 bytes in 1 blocks ==14771== indirectly lost: 120 bytes in 10 blocks ==14771== possibly lost: 0 bytes in 0 blocks ==14771== still reachable: 5,032 bytes in 190 blocks ==14771== suppressed: 0 bytes in 0 blocks ==14771== Reachable blocks (those to which a pointer was found) are not shown. ==14771== To see them, rerun with: --leak-check=full --show-reachable=yes ==14771== ==14771== For counts of detected and suppressed errors, rerun with: -v ==14771== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 45 from 10) code: #include <string> #include <sstream> #include <iostream> #include <memory> #include <odbc++/drivermanager.h> #include <odbc++/connection.h> #include <odbc++/preparedstatement.h> #include <odbc++/callablestatement.h> #include <odbc++/resultset.h> #include <odbc++/databasemetadata.h> #include <odbc++/resultsetmetadata.h> int main(int argc, char** argv) { int test; std::string dbConnectString = "DSN=htms02;UID=cms;PWD=cms1"; std::stringstream query; query << "select 1 as test"; try { std::unique_ptr<odbc::Connection> connection (odbc::DriverManager::getConnection(dbConnectString)); std::unique_ptr<odbc::Statement> statement (connection->createStatement()); std::unique_ptr<odbc::ResultSet> resultSet (statement->executeQuery(query.str())); while (resultSet->next()) { test = resultSet->getInt("test"); } std::cout << test << std::endl; resultSet.reset(); statement.reset(); connection.reset(); odbc::DriverManager::shutdown(); } catch(odbc::SQLException& e) { std::cout << std::endl << "error code: "<< e.getErrorCode() << std::endl << "error message: " << e.getMessage() << std::endl; } return 0; } -- simonsmicrophone.com |
From: Pete <pe...@ka...> - 2012-06-07 03:40:07
Attachments:
simple.cpp
|
Hi Simon, I'm not familiar with unique_ptr and used auto_ptr instead. I also isolated db I/O part into a function. Tell me if this works fine now. Pete > -----Original Message----- > From: Simon Walter [mailto:si...@gi...] > Sent: Thursday, 7 June 2012 1:09 p.m. > To: lib...@li... > Subject: Re: [libodbcxx-devel] segmentation fault help please > > > On 06/06/2012 07:27 PM, Pete wrote: > > > > Further to Jan's suggestions, unless you do: > > > > odbc::DriverManager::shutdown(); > > > > before exiting from your program you'll get leaks. > > > > Thanks for that Pete and Jan. I got this error upon exit: > > error code: 0 > error message: Failed to shutdown DriverManager: > [unixODBC][Driver Manager]Function sequence error > > As I'd gone back to using unique_ptr, I figured I should > reset() them in the order Jan specified - which makes sense. > > But there is still a memory leak. Is this to be expected? Am > I looking at something to do with the ODBC libs? > > $ valgrind --tool=memcheck --leak-check=full ./testODBCtds > ==14771== Memcheck, a memory error detector ==14771== > Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al. > ==14771== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun > with -h for copyright info ==14771== Command: ./testODBCtds ==14771== > 1 > ==14771== > ==14771== HEAP SUMMARY: > ==14771== in use at exit: 5,192 bytes in 201 blocks > ==14771== total heap usage: 1,788 allocs, 1,587 frees, > 1,455,615 bytes > allocated > ==14771== > ==14771== 160 (40 direct, 120 indirect) bytes in 1 blocks are > definitely lost in loss record 192 of 195 > ==14771== at 0x4023F50: malloc (vg_replace_malloc.c:236) > ==14771== by 0x429C1E3: nss_parse_service_list (nsswitch.c:622) > ==14771== by 0x429C926: __nss_database_lookup (nsswitch.c:164) > ==14771== by 0x402AEAB: ??? > ==14771== by 0x402BB6C: ??? > ==14771== by 0x4255994: getpwuid_r@@GLIBC_2.1.2 (getXXbyYY_r.c:253) > ==14771== by 0x42552FE: getpwuid (getXXbyYY.c:117) > ==14771== by 0x4378920: ??? (in /usr/lib/libodbc.so.1.0.0) > ==14771== by 0x4375445: ??? (in /usr/lib/libodbc.so.1.0.0) > ==14771== by 0x43617FF: ??? (in /usr/lib/libodbc.so.1.0.0) > ==14771== by 0x43330E2: SQLDriverConnect (in > /usr/lib/libodbc.so.1.0.0) > ==14771== by 0x40493FE: odbc::Connection::_connect(std::string > const&, unsigned short) (connection.cpp:227) ==14771== > ==14771== LEAK SUMMARY: > ==14771== definitely lost: 40 bytes in 1 blocks > ==14771== indirectly lost: 120 bytes in 10 blocks > ==14771== possibly lost: 0 bytes in 0 blocks > ==14771== still reachable: 5,032 bytes in 190 blocks > ==14771== suppressed: 0 bytes in 0 blocks > ==14771== Reachable blocks (those to which a pointer was > found) are not shown. > ==14771== To see them, rerun with: --leak-check=full > --show-reachable=yes ==14771== ==14771== For counts of > detected and suppressed errors, rerun with: -v ==14771== > ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 45 from 10) > > code: > > #include <string> > #include <sstream> > #include <iostream> > #include <memory> > #include <odbc++/drivermanager.h> > #include <odbc++/connection.h> > #include <odbc++/preparedstatement.h> > #include <odbc++/callablestatement.h> > #include <odbc++/resultset.h> > #include <odbc++/databasemetadata.h> > #include <odbc++/resultsetmetadata.h> > > > int main(int argc, char** argv) > { > int test; > std::string dbConnectString = "DSN=htms02;UID=cms;PWD=cms1"; > std::stringstream query; > query << "select 1 as test"; > > try > { > std::unique_ptr<odbc::Connection> connection > (odbc::DriverManager::getConnection(dbConnectString)); > std::unique_ptr<odbc::Statement> statement > (connection->createStatement()); > std::unique_ptr<odbc::ResultSet> resultSet > (statement->executeQuery(query.str())); > > while (resultSet->next()) > { > test = resultSet->getInt("test"); > } > std::cout << test << std::endl; > > resultSet.reset(); > statement.reset(); > connection.reset(); > > odbc::DriverManager::shutdown(); > } > catch(odbc::SQLException& e) > { > std::cout << std::endl << "error code: "<< > e.getErrorCode() << std::endl << "error message: " << > e.getMessage() << std::endl; > } > > return 0; > } > > > -- > simonsmicrophone.com > > -------------------------------------------------------------- > ---------------- > Live Security Virtual Conference > Exclusive live event will cover all the ways today's security > and threat landscape has changed and how IT managers can > respond. Discussions will include endpoint security, mobile > security and the latest in malware threats. > http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ > _______________________________________________ > libodbcxx-devel mailing list > lib...@li... > https://lists.sourceforge.net/lists/listinfo/libodbcxx-devel > |
From: Simon W. <si...@gi...> - 2012-06-07 05:02:27
|
On 06/07/2012 01:34 PM, Buck wrote: > > looks like the ``leak'' is in the C library's getpwuid(), which allocates > a ``static buffer'' for the returned struct passwd, no? if you're suggest- > ing that libodbc should call (the reentrant, and non-static struct passwd- > returning) getpwuid_r() directly, then you need to talk to the unixODBC > folks. but if you're saying GNU libc's getpwuid() should clean up at exit > or something, that's a different political arena > > anyways, thanks for sussing out the correct release semantics for the var- > ious libodbc++ objects Hi Buck, Thanks for setting me straight. I'm relatively new to c/c++ development on nix platforms and wasn't sure what I was seeing. I'm kind of surprised/annoyed that things are in this state - at least on Debian. It affects multi-threaded applications quite a bit. If I can't get them to sort it out, I'll have to steer clear of unixODBC for now. Or maybe use a different OS. Cheers, Simon -- simonsmicrophone.com |
From: Simon W. <si...@gi...> - 2012-06-07 05:03:23
|
On 06/07/2012 12:39 PM, Pete wrote: > Hi Simon, > > I'm not familiar with unique_ptr and used auto_ptr instead. I also isolated > db I/O part into a function. > > Tell me if this works fine now. It acts the same way. As Buck pointed out, it looks like the trouble is with unixODBC. Thanks for your help though. I'll see if I can't persuade Debian to package a newer version. Cheers, Simon -- simonsmicrophone.com |
From: Simon W. <si...@gi...> - 2012-06-19 02:23:53
|
On 06/08/2012 09:48 AM, Buck Huppmann wrote: > > On Wed, Jun 06, 2012 at 08:01:48PM -0900, Simon Walter wrote: >> >> On 06/07/2012 01:34 PM, Buck wrote: >>> >>> looks like the ``leak'' is in the C library's getpwuid(), which allocates >>> a ``static buffer'' for the returned struct passwd, no? if you're suggest- >>> ing that libodbc should call (the reentrant, and non-static struct passwd- >>> returning) getpwuid_r() directly, then you need to talk to the unixODBC >>> folks. but if you're saying GNU libc's getpwuid() should clean up at exit >>> or something, that's a different political arena >>> >>> anyways, thanks for sussing out the correct release semantics for the var- >>> ious libodbc++ objects >> >> Hi Buck, >> >> Thanks for setting me straight. I'm relatively new to c/c++ development >> on nix platforms and wasn't sure what I was seeing. I'm kind of >> surprised/annoyed that things are in this state - at least on Debian. It >> affects multi-threaded applications quite a bit. If I can't get them to >> sort it out, I'll have to steer clear of unixODBC for now. Or maybe use >> a different OS. > > Dang. 5,192 bytes over the lifetime of a process that get reclaimed at > process exit is that big a price to pay? > > cause, at least from glancing at > > http://sourceware.org/git/?p=glibc.git;a=blob;f=nss/getXXbyYY.c;h=336676ad555a0e7905318a11bbd0f9fc57fe8793;hb=HEAD > > it seems to me that it's 1 buffer per process and not per thread, so you > can spin up as many threads as you like and not ever leak more than that, > whereas i'd wager that another OS' process/thread/related kernel/subsys- > tem's object's overhead is gonna have a bigger footprint than that Sorry I've been sick with some kind of food poisoning. Better now. I must have sent the wrong trace. When using a MySQL db via ODBC, I was losing 4 bytes for every connect and disconnect. I built the MySQL ODBC driver from source, and it seems to crash less. It still crashes occasionally. It seems the problem is primarily with the driver. I'm going to try this on another platform - currently Debian 6. Cheers, Simon -- simonsmicrophone.com |