我在使用 Boost 共享指针时遇到了一些问题。指针指向的数据在不确定的时间突然被删除。在当前程序中(我尝试了许多其他变体),在 case case 之后,在循环恰好运行了 172 行之后(表中有 1000 行),数据boost::shared_array<TableFieldsMap> retArray
在 switch 构造中突然被删除。MYSQL_TYPE_DOUBLE
但仅当该方法被调用两次时。第一次运行完美。
具体来说,我将问题定位为在分配给 retArray 时使用的 map-key。当我使用硬编码字符串时它可以工作。但不是本地 shared_array (fieldNameArray) 的值(我首先有 scoped_array,但我理解这不应该工作),而不是本地变量 (tmpIndex)。
retArray[rowIndex]["value"] = boost::lexical_cast<long double>(row[i]); // This works.
// This doesn't work: retArray[rowIndex][fieldNameArray[i]] = boost::lexical_cast<long double>(row[i]);
// This doesn't work either: retArray[rowIndex][tmpIndex.c_str()] = boost::lexical_cast<long double (row[i]);
这是标题类:
#ifndef DATABASE_H
#define DATABASE_H
#include <map>
#include <string>
#include <iostream>
#include <vector>
using namespace std;
#include <glog/logging.h>
#include <boost/lexical_cast.hpp>
#include <boost/smart_ptr.hpp>
#include <boost/variant.hpp>
#include <mysql.h>
#include <cppconn/driver.h>
#include <cppconn/exception.h>
#include <cppconn/resultset.h>
#include <cppconn/statement.h>
#include <cppconn/prepared_statement.h>
#include "../globals/globals.hpp"
#include "../exception/cassandra_exception.hpp"
struct mapCompare
{
bool operator()(char const * a, char const * b)
{
return (strcmp(a, b) < 0);
}
};
typedef map<const char*, boost::variant<short, int, long double, char*>, mapCompare > TableFieldsMap;
struct DataSet
{
unsigned int rowCount;
boost::shared_array<TableFieldsMap>data;
};
class Database
{
private:
MYSQL *connection;
public:
Database();
~Database();
bool connect(const char *, const char *, const char *, const char *);
DataSet select(const char*);
};
#endif
和代码:
#include "database.hpp" Database::Database() { DLOG(INFO) << "::Database"; } Database::~Database() { DLOG(INFO) << "~Database"; if (connection) mysql_close(connection); } bool Database::connect(const char* server, const char* user, const char* password, const char* database) { DLOG(INFO) << ">> connect"; connection = mysql_init(NULL); if (!connection) { cout << "Error" << endl; return (false); } if (!mysql_real_connect(connection, server, user, password, database, 0, NULL, 0)) { cout << "Database init error (" << mysql_error(connection) << ")" << endl; } if (!connection) { cout << "Connection Failed!" << endl; return (false); } return (true); } DataSet Database::select(const char* query) { DLOG(INFO) << ">> select"; MYSQL_RES *resultSet; MYSQL_ROW row; unsigned int fieldCount; MYSQL_FIELD* field; // Query database. if (mysql_query(connection, query)) throw MyException(string("Database select error (") + mysql_error(connection) + ")"); // Handle result-set. resultSet = mysql_store_result(connection); if (resultSet == NULL) throw MyException(string("Database select error. Result-set is empty (") + mysql_error(connection) + ")"); // Initialize return array. unsigned int rowCount = mysql_num_rows(resultSet); boost::shared_array<TableFieldsMap> retArray(new TableFieldsMap[rowCount]); // Obtain field names and types. fieldCount = mysql_num_fields(resultSet); boost::shared_array<const char *> fieldNameArray(new const char* [fieldCount]); boost::scoped_array<enum_field_types> fieldTypeArray(new enum_field_types[fieldCount]); unsigned int fieldIndex = 0; while ((field = mysql_fetch_field(resultSet))) { fieldNameArray[fieldIndex] = field -> name; fieldTypeArray[fieldIndex++] = field -> type; } // Fix? string tmpIndex; // Load data from result-set. unsigned int rowIndex = 0; while ((row = mysql_fetch_row(resultSet)) != NULL) { // Fields of the row. for (unsigned int i = 0; i < fieldCount; i++) { if (row[i] == NULL) throw MyException("Database error. Null."); switch (fieldTypeArray[i]) { // Medium int & Integer. case MYSQL_TYPE_INT24 : case MYSQL_TYPE_LONG : retArray[rowIndex][fieldNameArray[i]] = boost::lexical_cast<int>(row[i]); break; case MYSQL_TYPE_DOUBLE : try { retArray[rowIndex]["value"] = boost::lexical_cast<long double>(row[i]); // This works. } catch (boost::bad_lexical_cast exception) { DLOG(ERROR) << "Error reading the phi table from database. Cast error. (" << rowIndex << ", " << row[i] << ")" << endl; throw MyException("Error reading the phi table from database. Cast error."); } // tmpIndex = string(fieldNameArray[i]); // This doesn't work: retArray[rowIndex][fieldNameArray[i]] = boost::lexical_cast<long double>(row[i]); // This doesn't work either: retArray[rowIndex][tmpIndex.c_str()] = boost::lexical_cast<long double>(row[i]); break; case MYSQL_TYPE_VARCHAR : // 15 case MYSQL_TYPE_VAR_STRING : // 253 case MYSQL_TYPE_STRING : // 254 retArray[rowIndex][fieldNameArray[i]] = row[i]; break; case MYSQL_TYPE_DECIMAL : // 0 case MYSQL_TYPE_TINY : // 1 case MYSQL_TYPE_SHORT : // 2 case MYSQL_TYPE_FLOAT : // 4 case MYSQL_TYPE_NULL : // 6 case MYSQL_TYPE_TIMESTAMP : // 7 case MYSQL_TYPE_LONGLONG : // 8 case MYSQL_TYPE_DATE : // 10 case MYSQL_TYPE_TIME : // 11 case MYSQL_TYPE_DATETIME : // 12 case MYSQL_TYPE_YEAR : // 13 case MYSQL_TYPE_NEWDATE : // 14 case MYSQL_TYPE_BIT : // 16 case MYSQL_TYPE_NEWDECIMAL : // 246 case MYSQL_TYPE_ENUM : // 247 case MYSQL_TYPE_SET : // 248 case MYSQL_TYPE_TINY_BLOB : // 249 case MYSQL_TYPE_MEDIUM_BLOB : // 250 case MYSQL_TYPE_LONG_BLOB : // 251 case MYSQL_TYPE_BLOB : // 252 default: DLOG(FATAL) << "Database error. Unsupported datatype"; throw MyException("Database error. Unsupported datatype"); break; } rowIndex++; } } mysql_free_result(resultSet); DataSet retStruct; retStruct.rowCount = rowCount; retStruct.data = retArray; return (retStruct); }
...
下面是调用方法:
include "My_database.hpp"
MyDatabase::MyDatabase(string server, string user, string password, string database)
{
DLOG(INFO) << "::MyDatabase (1)";
init(server.c_str(), user.c_str(), password.c_str(), database.c_str());
}
MyDatabase::MyDatabase(const char* server, const char* user, const char* password, const char* database)
{
DLOG(INFO) << "::MyDatabase (2)";
init(server, user, password, database);
}
MyDatabase::~MyDatabase()
{
DLOG(INFO) << "~MyDatabase";
}
void MyDatabase::init(const char* server, const char* user, const char* password, const char* database)
{
DLOG(INFO) << ">> init";
connect(server, user, password, database);
}
boost::shared_array<long double>MyDatabase::loadPhiTable()
{
DLOG(INFO) << ">> LoadPhiTable";
// Select from database.
DataSet selectData = select("SELECT value FROM phi");
boost::shared_array<TableFieldsMap>phiArray = selectData.data;
unsigned int rowCount = selectData.rowCount;
// Initialize return array.
boost::shared_array<long double> retArray(new long double[rowCount]);
unsigned int i = 0;
try
{
for (i = 0; i < rowCount; i++) retArray[i] = boost::get<long double>(phiArray[i]["value"]);
}
catch (boost::bad_get exception)
{
throw MyException(string("Error reading the phi table. Conversion error. (index: ") + boost::lexical_cast<string>(i) + ", value: " + boost::lexical_cast<string>(phiArray[i]["value"]) + ")");
}
return (retArray);
}
任何其他建议也将不胜感激。我的第一个 C++ 程序。