Increasing memory usage in sqlite3? - c++

I've written a console app which receives events via boost::interprocess memory and dumps the info into an sqlite3 database. While running the app I've noticed that, in the Windows task manager, the memory usage was cyclically increasing every... 30s-1min. This led me to believe that the problem lies within the main loop in which I execute my SQL. I've added some monitoring and apparently the sqlite3_memory_usage returns increasing results every couple loop iterations.
Can somebody tell me what am I doing wrong? Am I missing something I should de-allocate ?
Here are 2 strings I use to generate SQL
const std::string sql_insert =
"INSERT INTO EventsLog "
"(Sec, uSec, DeviceId, PmuId, EventId, Error, Msg) "
"VALUES (%ld, %ld, %ld, %d, %ld, %d, %Q)";
const std::string sql_create =
"CREATE TABLE IF NOT EXISTS EventsLog("
"Id INTEGER PRIMARY KEY AUTOINCREMENT, "
"Sec INTEGER NOT NULL, "
"uSec INTEGER NOT NULL, "
"DeviceId INTEGER NOT NULL, "
"PmuId INTEGER NOT NULL, "
"EventId INTEGER NOT NULL, "
"Error INTEGER NOT NULL, "
"Msg TEXT"
")";
In here, I generate the SQL INSERT command
std::string construct_sql_query
(const ELMessageData & data)
{
std::string query = "";
ptime jan1st1970 = ptime(date(1970,1,1));
ptime now = boost::posix_time::microsec_clock::universal_time();
time_duration delta = now - jan1st1970;
TimeVal time((uint32)delta.total_seconds(),
(uint32)now.time_of_day().fractional_seconds());
char * const sql = sqlite3_mprintf(sql_insert.c_str(),
time.tv_sec,
time.tv_usec,
data.getDeviceId(),
data.getPmuId(),
data.getEventId(),
(data.getIsError() ? 1 : 0),
data.getExMsg().c_str());
if(sql == NULL)
post_event(EvIOError("Failed to create the SQL command",
"StLoggingEvents::_construct_sql_query"));
query = std::string(sql);
sqlite3_free(sql);
return query;
} // construct_sql_query
Here's the main loop in which I execute the INSERT commands
while(true)
{
m_exchange_obj->wait(); // wait for the semaphore to be raised
const std::string sql = construct_sql_query
(m_exchange_obj->receive());
char ** err = NULL;
const int rc = sqlite3_exec(m_db_handle,
sql.c_str(),
NULL,
NULL,
err);
sqlite3_free(err);
if(rc != SQLITE_OK)
{
LERR_ << "Error while inserting into the database";
LERR_ << "Last SQL Query : ";
LERR_ << sql;
}
else
{
LDBG_ << "Event logged...";
LDBG_ << "Sqlite3 memory usage : "
<< sqlite3_memory_used();
}
}

I second the suggestion of trying this under valgrind. You may also want to look at google's tcmalloc replacement... It can print pretty graphs showing you all your leaks... That said, I hope you get the answer for this... I plan on using SQLite in an upcoming project...

How are you determining your memory usage? You may not have a real leak.
If you are on a windows system and using visual studio, compile in debug mode and use the memory debugging macros to find your leaks.
If you are on a unix based system, try valgrind / memcheck.
I think OS X's xcode also detects leaks too.

Related

How to work with .mdb databases using Visual C++ (Not C++/CLI)?

I'm becoming insane currently because I am not able to find a solution to the following task:
I want to
read out data from tables inside a MS Access .mdb database
manipulate said data and
write it back into the same database
do all that with Visual C++ (not with CLI as I would have to adjust lots of already existing code)
To do so, I tried to use the solution provided here, which uses ADO to work with the Northwind 2007.accdb database (It shouldn't be a problem that they access .accdb instead of .mdb right?). I copypasted the code given there into an empty project in VS2017 x64, only adjusted the sourcepath of the Northwind database and changed the following line
hr = pConn->Open(bstrConnect, "admin", "", ADODB::adConnectUnspecified);
to
HRESULT hr = pConn->Open(bstrConnect, "admin", "", ADODB::adConnectUnspecified);
because otherwise hr isn't defined. (Was this an incorrect adjustment?)
I have MS Access 2016 64bit version installed.
Now here is my code:
#import <C:\\Program Files\\Common Files\\System\\ado\\msado15.dll> rename( "EOF", "AdoNSEOF" )
#include <iostream>
using namespace std;
int main() {
_bstr_t bstrConnect = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\\Users\\Public\\Downloads\\Northwind 2007.accdb;";
// Shows the Data Access Method used in this sample.
const char* DAM = "ADO";
ADODB::_ConnectionPtr pConn("ADODB.Connection");
HRESULT hr = pConn->Open(bstrConnect, "admin", "", ADODB::adConnectUnspecified);
if (SUCCEEDED(hr)) {
cout << DAM << ": Successfully connected to database. Data source name:\n "
<< pConn->GetConnectionString() << endl;
// Prepare SQL query.
_bstr_t query = "SELECT Customers.[Company], Customers.[First Name] FROM Customers;";
cout << DAM << ": SQL query:\n " << query << endl;
// Excecute the query and create a record set.
ADODB::_RecordsetPtr pRS("ADODB.Recordset");
hr = pRS->Open(query,
_variant_t((IDispatch *)pConn, true),
ADODB::adOpenUnspecified,
ADODB::adLockUnspecified,
ADODB::adCmdText);
if (SUCCEEDED(hr)) {
cout << DAM << ": Retrieve schema info for the given result set: " << endl;
ADODB::Fields* pFields = NULL;
hr = pRS->get_Fields(&pFields);
if (SUCCEEDED(hr) && pFields && pFields->GetCount() > 0) {
for (long nIndex = 0; nIndex < pFields->GetCount(); nIndex++) {
cout << " | " << _bstr_t(pFields->GetItem(nIndex)->GetName());
}
cout << endl;
} else {
cout << DAM << ": Error: Number of fields in the result set is 0." << endl;
}
cout << DAM << ": Fetch the actual data: " << endl;
int rowCount = 0;
while (!pRS->AdoNSEOF) {
for (long nIndex = 0; nIndex < pFields->GetCount(); nIndex++) {
cout << " | " << _bstr_t(pFields->GetItem(nIndex)->GetValue());
}
cout << endl;
pRS->MoveNext();
rowCount++;
}
cout << DAM << ": Total Row Count: " << rowCount << endl;
}
pRS->Close();
pConn->Close();
cout << DAM << ": Cleanup. Done." << endl;
} else {
cout << DAM << ": Unable to connect to data source: " << bstrConnect << endl;
}
return 1;
}
The code compiles but in msado15.tlh which is generated by the import directive there are 52 errors E0102 shown (for different lines but always the same error), the description being: The Forward declaration of the enumeration type doesn't comply to the standard (rough translation, I think it gets the point across). (As a side question: When using the import directive, where in the project properties do I have to link the msado15.dll path? I added the C:\Program Files\Common Files\System\ado path to the Include directory, was that right?)
Furthermore running the .exe or executing it in Powershell doesn't work, Windows gives out the message "MYPROGRAM.exe isn't running anymore" with the only option to close the program.
What am I doing wrong? Have I chosen the wrong approach to what in my eyes seems to be a task that should be quite easy to solve (shouldn't be that hard to read out a damn table in Visual C++)?
Is there maybe a better way to work with .mdb databases (like using DAO, ODBC or OLE DB for example) and are there working up-to-date code samples that one could work with or a nice documentation/tutorial that explains step-by-step how to connect to the database and shows how to read from and write into it?
EDIT1: A_Singh7 provided the following solutions:
define ghr as a global variable
change the return value of the main function to 0
Use the code provided here
The first two solutions didn't do the trick so I tried it with the code from solution 3. This is the output in Powershell i receive:
ADO: Successfully connected to database. Data source name:
Provider=Microsoft.ACE.OLEDB.12.0;User ID=admin;Data Source=C:\Users\Public\Downloads\Northwind 2007.accdb;Mode=Share Deny None;Jet OLEDB:System database="";Jet OLEDB:Registry Path="";Jet OLEDB:Database Password="";Jet OLEDB:Engine Type=5;Jet OLEDB:Database Locking Mode=1;Jet OLEDB:Global Partial Bulk Ops=2;Jet OLEDB:Global Bulk Transactions=1;Jet OLEDB:New Database Password="";Jet OLEDB:Create System Database=False;Jet OLEDB:Encrypt Database=False;Jet OLEDB:Don't Copy Locale on Compact=False;Jet OLEDB:Compact Without Replica Repair=False;Jet OLEDB:SFP=False;Jet OLEDB:Support Complex Data=False;Jet OLEDB:Bypass UserInfo Validation=False;Jet OLEDB:Limited DB Caching=False;Jet OLEDB:Bypass ChoiceField Validation=False;
ADO: SQL query
SELECT Customers.[Company], Customers.[First Name] FROM Customers;
Afterwards, the .exe sadly crashes and I still have to figure out why. Nonetheless establishing a connection to the database seems to work, which was the main issue I had.
Try to declare hr as a global variable.
That’s like,
#include <iostream>
using namespace std;
HRESULT hr;
int main ()
{
// your code
// the line hr = pConn->Open(bstrConnect, "admin", "", ADODB::adConnectUnspecified); should remain as it is
}
First try the above, if it doesn’t work, try changing return 1; to return 0;.
If that even doesn’t work, see here:
http://msdn.microsoft.com/en-us/library/cc811599.aspx
Take help from here after that :
Connecting to MS Access database using C++ using Visual Studio 2008
Here you just need to include the file stafdx.h as a header to make the code work perfectly.

C++ - Mysql connector

I'm using the c++ mysql connector to do operations in my mysql database.
My c++ program is a real time application (rest api) which is always running in the cloud, always waiting for user requests.
When i start my program for the first type i automatically create a connection to the database (the fields for the connector i load from a configuration file). Example:
conDataBase = new ConDatabase;
if (!conDataBase->Init()) return false;
The conDataBase is a global pointer accessible to all classes.
The Init() function:
bool conDatabase::Init()
{
GetParameterStr("DATABASE", "HOST", "", hostname, 255);
db_hostname = hostname;
GetParameterStr("DATABASE", "USER", "", user, 255);
db_user = user;
GetParameterStr("DATABASE", "PASSWORD", "", password, 255);
db_password = password;
GetParameterStr("DATABASE", "SCHEMA", "", schema, 255);
db_schema = schema;
printf("DATABASE: Connecting to %s \n",db_hostname.c_str());
printf("DATABASE: Connecting at %s with user %s \n",db_schema.c_str(), db_user.c_str());
try
{
driver = get_driver_instance();
con = driver->connect(db_hostname.c_str(), db_user.c_str(), db_password.c_str());
con->setSchema(db_schema.c_str());
stmt = con->createStatement();
printf("DATABASE: Connected to database... OK \n");
return true;
}
catch (sql::SQLException &e)
{
std::cout << "# ERR: SQLException in " << __FILE__;
std::cout << "(" << __FUNCTION__ << ") on line " << __LINE__ << std::endl;
std::cout << "# ERR: " << e.what();
std::cout << " (MySQL error code: " << e.getErrorCode();
std::cout << ", SQLState: " << e.getSQLState() << " )" << std::endl;
return false;
}
}
So when i receive a request for example to list the userInfo in the userInfo request class i call the global pointer for the database class like this:
conDataBase->GetUserInfo(// the parameters);
Inside the GetUserInfo() i build my query like this:
res = stmt->executeQuery(query);
Its works but my real doubt is: Its is necessary to delete the pointer from mysqlconnector (res, pstmt, con, etc)?. I'm scary about memory leaks in future. I'm only delete the pointers when the program exits but it is a real time program reason why he is not expected to be finished. If i delete the pointer in each query, insert etc (like the mysqlconnector examples do) in next time i have segmentation fault because when i run the program in first time i create the database pointers con, res, etc, so i cannot delete these pointers in each database operation because if i do this, in next time the pointers are deleted and i dont have access to him and its result in segmentation fault. Whats is the solution in these case to prevent memory leaks in future?
For such cases you can write a connectionManager class. It can be used to provide api's for :
1- creating and maintaining connection pool,
2- getConnection api to get a connection instance from the pool,
3- a release connection api to put the connection instance back into opened connection's pool,
4- you should be using stl containers to store opened connections, etc

SQLite in C++. DB is BUSY (Multithread)

I've got a problem. I'm using SQLite3 in my C++ project. In the log, I've got errors: DB is locked error code 5. As I know, error code 5 means that DB is busy. To solve this, I started to use WAL journal mode. But it doesn't help.
In my program, I've got 2 connections to the same DB. I use mutexes for both DB connections.
I'm opening connections with this code:
if (sqlite3_open_v2(db_path.c_str(), &this->db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_NOMUTEX, 0) ) {
LOG4CPLUS_FATAL(this->logger, "Can not open/create DB " << sqlite3_errmsg(db));
sqlite3_close(this->db);
}
if (sqlite3_exec(this->db, "PRAGMA journal_mode = WAL;", 0, 0, &err)) {
LOG4CPLUS_ERROR(this->logger, "SQL det journal mode error: " << err);
sqlite3_free(err);
}
The first connection is used for inserting data to the DB. It happens 4 times every second.
The second connection is used for starting transaction, selecting, updating, deleting data, and committing. It happens every 5 seconds.
I'm getting errors from the first connection.
Please help me to solve this problem.
Update:
First connection:
void readings_collector::flushToDb()
{
this->db_mutex.lock();
LOG4CPLUS_DEBUG(this->logger, "Flush to DB start.");
const char *query = "INSERT INTO `readings` (`sensor_id`, `value`, `error`, `timestamp`) VALUES (?,?,?,?)";
sqlite3_stmt *stmt = NULL;
int rc = sqlite3_prepare_v2(this->db, query, -1, &stmt, NULL);
if (SQLITE_OK != rc) {
LOG4CPLUS_ERROR(this->logger, "sqlite prepare insert statment error: " << sqlite3_errmsg(this->db));
}
LOG4CPLUS_TRACE(this->logger, "--------------------");
LOG4CPLUS_TRACE(this->logger, this->readings.size());
while(!this->readings.empty()) {
sensor::reading temp_reading = this->readings.front();
this->readings.pop();
LOG4CPLUS_TRACE(this->logger, "Reading " << temp_reading.sensor_id << " : " << temp_reading.value << " : " << temp_reading.error << " : " << temp_reading.timestamp);
sqlite3_clear_bindings(stmt);
sqlite3_bind_int(stmt, 1, temp_reading.sensor_id);
sqlite3_bind_text(stmt, 2, temp_reading.value.c_str(), sizeof(temp_reading.value.c_str()), NULL);
sqlite3_bind_int(stmt, 3, temp_reading.error);
sqlite3_bind_int(stmt, 4, temp_reading.timestamp);
rc = sqlite3_step(stmt);
if (SQLITE_DONE != rc) {
LOG4CPLUS_ERROR(this->logger, "sqlite insert statment exec error: " << sqlite3_errmsg(this->db) << "; status: " << rc);
}
}
sqlite3_finalize(stmt);
LOG4CPLUS_TRACE(this->logger, "Flush to DB finish.");
this->db_mutex.unlock();
}
Second connection:
void dataSend_task::sendData()
{
this->db_mutex.lock();
char *err = 0;
LOG4CPLUS_INFO(this->logger, "Send data function");
if (sqlite3_exec(this->db, "BEGIN TRANSACTION", 0, 0, &err)) {
LOG4CPLUS_ERROR(this->logger, "SQL exec error: " << err);
sqlite3_free(err);
}
if (sqlite3_exec(this->db, this->SQL_UPDATE_READINGS_QUERY, 0, 0, &err)) {
LOG4CPLUS_ERROR(this->logger, "SQL exec error: " << err);
sqlite3_free(err);
}
this->json.clear();
this->readingsCounter = 0;
if (sqlite3_exec(this->db, this->SQL_SELECT_READINGS_QUERY, +[](void *instance, int x, char **y, char **z) {
return static_cast<dataSend_task *>(instance)->callback(0, x, y, z);
}, this, &err)) {
LOG4CPLUS_ERROR(this->logger, "SQL exec error: " << err);
sqlite3_free(err);
} else {
LOG4CPLUS_TRACE(this->logger, "Json data: " << this->json);
if (this->curlSend()) {
if (sqlite3_exec(this->db, this->SQL_DELETE_READINGS_QUERY, 0, 0, &err)) {
LOG4CPLUS_ERROR(this->logger, "SQL exec error: " << err);
sqlite3_free(err);
}
}
}
if (sqlite3_exec(this->db, "COMMIT", 0, 0, &err)) {
LOG4CPLUS_ERROR(this->logger, "SQL exec error: " << err);
sqlite3_free(err);
}
this->db_mutex.unlock();
this->json.clear();
}
As you've no doubt realized, SQLite only allows one connection at a time to be be updating the database.
From the code you have pasted, it looks as though you have two separate mutexes, one for the readings_collector instance, another for the dataSend_task instance. These would protect against multiple executions of each of the two functions but not against both of those functions running at once.
It wasn't that clear from your question what the purpose of the mutexes is, but it certainly isn't going to prevent both of those connections from simultaneously trying to update the database.
I can suggest two approaches to fix your problem.
The first would be to use a single shared mutex between those two instances, so that only one of them at a time can be updating the database.
The second would be to take advantage of the facilities SQLite provides for resolving contention when accessing the database. SQLite allows you to install a 'busy handler' which will be called in the event that an attempt is made to access a database which is already locked by another thread or process. The busy handler can take whatever action is desired, but the simplest case is normally just to wait a while and try again, which is catered for by the built in busy handler which you can install by calling sqlite3_busy_timeout.
For example, immediately after opening your database connection, you could do this:
sqlite3_busy_timeout(this->db, 1000); // Wait 1000mS if busy
It is also possible to set such a timeout by command, using the busy_timeout pragma.
You may also wish to consider starting your transaction using BEGIN IMMEDIATE TRANSACTION or BEGIN EXCLUSIVE TRANSACTION so that the transaction can be guaranteed to complete without blocking. See the documentation on transactions.
Please check these two Stack Overflow posts. They seem to be related to your issue.
Can different connections of the same sqlite's database begin transactions concurrently?
If you read the SQLite documentation, you will see that it supports
multiple connections for reading only, you cannot write to the
database from mulitple connections, because it's not designed for
that.
Read and Write Sqlite database data concurrently from multiple connections
Multiple processes can have the same sqlite database open at the same
time, several read accesses can be satisfied in parallel.
In case of write, a single write to the database does lock the
database for a short time, nothing, even reading, can access the
database file at all.
Beginning with version 3.7.0, a new “Write Ahead Logging” (WAL) option
is available. In which Reading and writing can proceed concurrently.
By default, WAL is not enabled. To turn WAL on, please refer to Sqlite
documentation.

DeviceIoControl, passing an int to driver

Driver:
PIO_STACK_LOCATION pIoStackLocation = IoGetCurrentIrpStackLocation(pIrp);
PVOID pBuf = pIrp->AssociatedIrp.SystemBuffer;
switch (pIoStackLocation->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_TEST:
DbgPrint("IOCTL IOCTL_TEST.");
DbgPrint("int received : %i", pBuf);
break;
}
User-space App:
int test = 123;
int outputBuffer;
DeviceIoControl(hDevice, IOCTL_SET_PROCESS, &test, sizeof(test), &outputBuffer, sizeof(outputBuffer), &dwBytesRead, NULL);
std::cout << "Output reads as : " << outputBuffer << std::endl;
The user-space application prints out the correct value received back through the output buffer, but in debug view, the value printed out seems to be garbage (ie: "int received : 169642096")
What am I doing wrong?
As said by the previous user, you are printing the address of the variable, not the content.
I strongly suggest you to take a look to the following Driver Development tutorials:
http://www.opferman.com/Tutorials/

libmysqlclient.18.dylib memory leak

PROBLEM: What's the cause of the memory leaks?
SITUATION:
I've build a simple command line program using C++ together with MySQL using the MySQL C API
The problem is, the program has many "minor" memory leaks from the object malloc xx bytes" with xx ranging from a few bytes to 8 kb. All of the leaks links to the library libmysqlclient.18.dylib.
I've already removed all the mysql_free_result() from the code to see if that was the problem, but its still the same.
My MySQL code mainly consists of simple code like:
to connect:
MYSQL *databaseConnection()
{
// declarations
MYSQL *connection = mysql_init(NULL);
// connecting to database
if(!mysql_real_connect(connection,SERVER,USER,PASSWORD,DATABASE,0,NULL,0))
{
std::cout << "Connection error: " << mysql_error(connection) << std::endl;
}
return connection;
}
executing a query:
MYSQL_RES *getQuery(MYSQL *connection, std::string query)
{
// send the query to the database
if (mysql_query(connection, query.c_str()))
{
std::cout << "MySQL query error: " << mysql_error(connection);
exit(1);
}
return mysql_store_result(connection);
}
example of a query:
void resetTable(std::string table)
{
MYSQL *connection = databaseConnection();
MYSQL_RES *result;
std::string query = "truncate table " + table;
result = getQuery(connection, query);
mysql_close(connection);
}
First of all: Opening a new connection for every query (like you're doing in resetTable()) is incredibly wasteful. What you really want to do is open a single connection when the application starts, use that for everything (possibly by storing the connection in a global), and close it when you're done.
To answer your question, though: You need to call mysql_free_result() on result sets once you're done with them.