Post by zeeshan on Dec 21, 2013 6:36:56 GMT
I dont know much about C++ but i have this code that runs as a server code. It will shut down after about a day of running, I belive its due to memory leak.. I was hopeing someone could help.? Here are the pastebins of the code.
Main.cpp
pastebin.com/ky99F4Rd
and main.h
pastebin.com/axribzpx
i have a few other cpp but did not think it would help? if you need them i can post them.
mysql.cpp (issue was happening befor adding this, but seems to get worst)
and
rgn.cpp (not sure what it is for) but ill post it too.
pastebin.com/vAyrzu0w
rgn.h
pastebin.com/CNc9KfR5
.h file
Main.cpp
pastebin.com/ky99F4Rd
and main.h
pastebin.com/axribzpx
i have a few other cpp but did not think it would help? if you need them i can post them.
mysql.cpp (issue was happening befor adding this, but seems to get worst)
and
rgn.cpp (not sure what it is for) but ill post it too.
pastebin.com/vAyrzu0w
rgn.h
pastebin.com/CNc9KfR5
#include "main.h"
mysql::mysql(std::string host, std::string username, std::string password) : host(""), username(""), password("") {
this->connection = mysql_init(NULL);
if (this->connection == NULL) {
throw std::runtime_error(mysql_error(this->connection));
}
my_bool reconnect = 1;
mysql_options(this->connection, MYSQL_OPT_RECONNECT, &reconnect);
// this->connect(host, username, password);
}
void mysql::connect(std::string host, std::string username, std::string password) {
// mysql_close(this->connection);
this->host = host;
this->username = username;
this->password = password;
my_bool reconnect = 1;
mysql_options(this->connection, MYSQL_OPT_RECONNECT, &reconnect);
if (mysql_real_connect(this->connection, this->host.c_str(), this->username.c_str(), this->password.c_str(), NULL, 0, NULL, 0) == NULL) {
throw std::runtime_error("connect error " + std::string(mysql_error(this->connection)));
}
reconnect = 1;
mysql_options(this->connection, MYSQL_OPT_RECONNECT, &reconnect);
}
void mysql::connect() {
mysql_close(this->connection);
if (mysql_real_connect(this->connection, this->host.c_str(), this->username.c_str(), this->password.c_str(), NULL, 0, NULL, 0) == NULL) {
throw std::runtime_error("connect error " + std::string(mysql_error(this->connection)));
}
my_bool reconnect = 1;
mysql_options(this->connection, MYSQL_OPT_RECONNECT, &reconnect);
}
void mysql::use(std::string database) {
mysql_ping(this->connection);
if (mysql_select_db(this->connection, database.c_str())) {
throw std::runtime_error(mysql_error(this->connection));
}
}
unsigned long long mysql::lastId() {
mysql_ping(this->connection);
return mysql_insert_id(this->connection);
}
std::unique_ptr<std::vector<std::map<std::string, std::string>>> mysql::query(std::string sql, std::vector<std::string> params) {
std::map<std::string, MYSQL_STMT*>::iterator query;
if (mysql_ping(this->connection) != 0) {
cout << "reconnect\n";
this->connect();
}
cout << "query\n";
int errorCode = 0;
query = this->statements.find(sql);
if (query == this->statements.end()) {
std::pair<std::string, MYSQL_STMT*> statement;
statement = std::pair<std::string, MYSQL_STMT*>(sql, mysql_stmt_init(this->connection));
if (statement.second == NULL) {
throw std::runtime_error("a" + std::string(mysql_error(this->connection)));
}
my_bool tmp = 1;
mysql_stmt_attr_set(statement.second, STMT_ATTR_UPDATE_MAX_LENGTH, &tmp);
this->statements.insert(statement);
if (mysql_stmt_prepare(statement.second, sql.c_str(), sql.length())) {
throw std::runtime_error("b" + std::string(mysql_stmt_error(statement.second)));
}
query = this->statements.find(sql);
}
unsigned long paramCount = mysql_stmt_param_count(query->second);
MYSQL_BIND* paramBinds;
char** paramBuffers;
unsigned long* paramDataLength;
if (paramCount > 0) {
if (paramCount > params.size()) {
throw std::runtime_error("Not enough parameters given.");
} else if (paramCount < params.size()) {
throw std::runtime_error("To many parameters given.");
}
paramBinds = (MYSQL_BIND*) malloc (paramCount * sizeof(MYSQL_BIND));
memset(paramBinds, 0, paramCount * sizeof(MYSQL_BIND));
paramBuffers = (char**) malloc (paramCount * sizeof(char*));
paramDataLength = (unsigned long*) malloc (paramCount * sizeof(unsigned long));
for (unsigned int i = 0; i < paramCount; i++) {
paramBuffers[i] = (char*) malloc (params[i].length()+1 * sizeof(char));
strcpy(paramBuffers[i], params[i].c_str());
paramDataLength[i] = params[i].length();
paramBinds[i].buffer_type = MYSQL_TYPE_STRING;
paramBinds[i].buffer = paramBuffers[i];
paramBinds[i].buffer_length = params[i].length();
paramBinds[i].is_null = 0;
paramBinds[i].length = ¶mDataLength[i];
}
if (mysql_stmt_bind_param(query->second, paramBinds) != 0) {
throw std::runtime_error("c" + std::string(mysql_stmt_error(query->second)));
}
}
if ((errorCode=mysql_stmt_execute(query->second)) != 0) {
if (errorCode == 1) {
this->connect();
if (mysql_stmt_execute(query->second) != 0) {
cout << std::string(mysql_stmt_error(query->second)) << "\n";
cout << std::string(mysql_stmt_error(query->second)) << "\n";
throw std::runtime_error("de" + std::string(mysql_stmt_error(query->second)));
}
} else {
throw std::runtime_error("d" + itostr(errorCode) + std::string(mysql_stmt_error(query->second)));
}
}
if (mysql_stmt_store_result(query->second)) {
throw std::runtime_error("e" + std::string(mysql_stmt_error(query->second)));
}
MYSQL_RES *resultMetadata = mysql_stmt_result_metadata(query->second);
if (resultMetadata == NULL) { // no results
mysql_stmt_free_result(query->second);
if (paramCount > 0) {
for (unsigned int i = 0; i < paramCount; i++) {
free(paramBuffers[i]);
}
free(paramBinds);
free(paramBuffers);
free(paramDataLength);
}
return std::unique_ptr<std::vector<std::map<std::string, std::string>>>(new std::vector<std::map<std::string, std::string>>());
}
unsigned int fields = mysql_num_fields(resultMetadata);
MYSQL_BIND* resultBinds = (MYSQL_BIND*) malloc (fields * sizeof(MYSQL_BIND));
memset(resultBinds, 0, fields * sizeof(MYSQL_BIND));
char** resultBuffers = (char**) malloc (fields * sizeof(char*));
unsigned long* resultDataLength = (unsigned long*) malloc (fields * sizeof(unsigned long));
MYSQL_FIELD *field;
std::vector<std::string> fieldNames;
std::unique_ptr<std::vector<std::map<std::string, std::string>>> results(new std::vector<std::map<std::string, std::string>>());
for (unsigned int i=0; i < fields; i++) {
field = mysql_fetch_field(resultMetadata);
resultBuffers[i] = (char*) malloc (field->max_length+1 * sizeof(char));
resultBinds[i].buffer_type = MYSQL_TYPE_STRING;
resultBinds[i].buffer = resultBuffers[i];
resultBinds[i].buffer_length = field->max_length+1;
resultBinds[i].is_null = 0;
resultBinds[i].length = &resultDataLength[i];
fieldNames.emplace_back(std::string(field->name));
}
mysql_stmt_bind_result(query->second, resultBinds);
while (mysql_stmt_fetch(query->second) == 0) {
results->emplace_back();
for (unsigned int i=0; i < fields; i++) {
results->back().insert(std::pair<std::string, std::string>(fieldNames[i], std::string(resultBuffers[i])));
}
}
mysql_free_result(resultMetadata);
mysql_stmt_free_result(query->second);
if (paramCount > 0) {
for (unsigned int i = 0; i < paramCount; i++) {
free(paramBuffers[i]);
}
free(paramBinds);
free(paramBuffers);
free(paramDataLength);
}
for (unsigned int i = 0; i < fields; i++) {
free(resultBuffers[i]);
}
free(resultBinds);
free(resultBuffers);
free(resultDataLength);
return results;
}
std::unique_ptr<std::vector<std::map<std::string, std::string>>> mysql::query(std::string sql) {
std::map<std::string, MYSQL_STMT*>::iterator query;
mysql_ping(this->connection);
query = this->statements.find(sql);
if (query == this->statements.end()) {
std::pair<std::string, MYSQL_STMT*> statement;
statement = std::pair<std::string, MYSQL_STMT*>(sql, mysql_stmt_init(this->connection));
if (statement.second == NULL) {
throw std::runtime_error(mysql_error(this->connection));
}
my_bool tmp = 1;
mysql_stmt_attr_set(statement.second, STMT_ATTR_UPDATE_MAX_LENGTH, &tmp);
this->statements.insert(statement);
if (mysql_stmt_prepare(statement.second, sql.c_str(), sql.length())) {
throw std::runtime_error(mysql_stmt_error(statement.second));
}
query = this->statements.find(sql);
}
if (mysql_stmt_execute(query->second)) {
throw std::runtime_error(mysql_stmt_error(query->second));
}
if (mysql_stmt_store_result(query->second)) {
throw std::runtime_error(mysql_stmt_error(query->second));
}
MYSQL_RES *resultMetadata = mysql_stmt_result_metadata(query->second);
if (resultMetadata == NULL) {
throw std::runtime_error(mysql_stmt_error(query->second));
}
unsigned int fields = mysql_num_fields(resultMetadata);
MYSQL_BIND* resultBinds = (MYSQL_BIND*) malloc (fields * sizeof(MYSQL_BIND));
memset(resultBinds, 0, fields * sizeof(MYSQL_BIND));
char** resultBuffers = (char**) malloc (fields * sizeof(char*));
unsigned long* dataLength = (unsigned long*) malloc (fields * sizeof(unsigned long));
MYSQL_FIELD *field;
std::vector<std::string> fieldNames;
std::unique_ptr<std::vector<std::map<std::string, std::string>>> results(new std::vector<std::map<std::string, std::string>>());
for (unsigned int i=0; i < fields; i++) {
field = mysql_fetch_field(resultMetadata);
resultBuffers[i] = (char*) malloc (field->max_length+1 * sizeof(char));
resultBinds[i].buffer_type = MYSQL_TYPE_STRING;
resultBinds[i].buffer = resultBuffers[i];
resultBinds[i].buffer_length = field->max_length+1;
resultBinds[i].is_null = 0;
resultBinds[i].length = &dataLength[i];
fieldNames.emplace_back(std::string(field->name));
}
mysql_stmt_bind_result(query->second, resultBinds);
while (mysql_stmt_fetch(query->second) == 0) {
results->emplace_back();
for (unsigned int i=0; i < fields; i++) {
results->back().insert(std::pair<std::string, std::string>(fieldNames[i], std::string(resultBuffers[i])));
}
}
return results;
}
mysql::~mysql() {
for (auto& kv : this->statements) {
mysql_stmt_close(kv.second);
}
mysql_close(this->connection);
}
.h file
#ifndef MYSQL_H_INCLUDED
#define MYSQL_H_INCLUDED
typedef std::unique_ptr<std::vector<std::map<std::string, std::string>>> mysqlResult;
class mysql {
private:
MYSQL *connection;
std::map<std::string, MYSQL_STMT*> statements;
std::string host;
std::string username;
std::string password;
public:
mysql(std::string host, std::string username, std::string password);
void connect(std::string host, std::string username, std::string password);
void connect();
mysqlResult query(std::string sql, std::vector<std::string> param);
mysqlResult query(std::string sql);
unsigned long long lastId();
void use(std::string database);
~mysql();
};
#endif // MYSQL_H_INCLUDED