gpt4 book ai didi

c++ - 数据突然从 Boost shared_array/ptr 中删除

转载 作者:搜寻专家 更新时间:2023-10-31 01:14:44 25 4
gpt4 key购买 nike

我在使用 Boost 共享指针时遇到了一些问题。指针指向的数据在不确定的时间突然被删除。在当前程序中(我尝试过许多其他变体)boost::shared_array<TableFieldsMap> retArray 的数据案例后在switch构造中突然被删除MYSQL_TYPE_DOUBLE这种情况下,在循环恰好运行了 172 行之后(表中有 1000 行)。但仅当该方法被调用两次时。第一次运行非常完美。

具体来说,我指出问题出在分配给 retArray 时使用的映射键。当我使用硬编码字符串时它起作用了。但不是局部 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++ 程序。

最佳答案

问题是

boost::shared_array<const char *> fieldNameArray = ...;

不拥有数组的元素,因此当间接数据消失时,它们将作为悬挂指针保留下来。如果 mysql_fetch_field 返回的指针间接指向合并的数据,这可能发生在 MySQL API 中。

最简单的修复方法是将 fieldNameArray 更改为包含 std::string

关于c++ - 数据突然从 Boost shared_array/ptr 中删除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10977445/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com