0

我在实现列存储数据库系统时遇到了内存分配问题。这尤其是实现 MySql 连接器以将表导入我的数据库的一部分。

假设我有以下向量:

 std::vector <void *> data;

我有一个检查类型以将数据添加到指针的函数,如下所示: 如您所见,对于每一列,我们都有一个 void * 添加到向量中。

for(int c = 0; c != numCols; c++){

      // ...
      case BOOL_TYPE: {
                 bool *b;
                 data.push_back((void *) b);
             }
             break;
      // ... 
}

现在另一个读取表行的函数需要添加数据

    while (mysqlpp::Row row = res.fetch_row()) {
                    for (int c = 0; c != numCols; c++) {
                        // ...
                        switch (colType){
                    case BOOL_TYPE: {
                        if(!isNull){
                            bool val = row[c];
                            data[c] = new char[sizeof(val)];
                            data[c] = val;
                        }
                    }
                    break;

                   //... more types

                }



                    }
   }

我担心这些行:

 data[c] = new char[sizeof(val)];
 data[c] = val;

我对 C++ 和内存管理非常陌生,所以我不确定如何每次都为 void * 分配更多内存然后添加值?

编辑 这是一个列存储数据库,我将数据存储在列而不是行中。需要明确的是,我需要一种干净的方式将 mySQL(行存储数据库)中的数据添加到我的列中。

我的问题的一个简单解决方案是,如果我可以使用 MySql++ 获取表中的行数?然后我可以最初分配那么多行 *(datattype 的大小)字节并填充这个内存。

4

2 回答 2

1

使用原始动态分配的数组很快就会变得不方便,而且容易发生内存泄漏。

我建议使用变体类型来存储值,而无需进行手动内存管理。例如boost::variant

typedef boost::variant<
    std::nullptr_t, // for DB NULL
    bool,           // for DB BOOL
    intmax_t,       // for DB Integers
    double,         // for DB Reals
    std::string     // for DB varchar
    > Value;

接着:

//...
data.push_back(Value()); // nullptr value

或者只是data.resize(column_count)

然后:

// ...
bool val = row[c];
data[c] = val;

处理数据库数据有两种主要方法:

  1. 强类型。在这种情况下,您的内存列存储确切的类型,例如std::vector<int>Integer DB 列。或者,按行,struct为每个查询定义一条记录,行存储为std::vector<Record>.
  2. 弱类型。类似于std::vector<Variant>列或std::vector<std::vector<Variant>>行的东西。很难做出更好的变体类型boost::variant

看起来您使用弱类型的方式void*作为变体类型。void*是类型不安全的,这意味着在编译时没有发现任何错误,例如内存管理错误,比如转换void*为错误的类型;或忘记释放内存或多次释放它。使用void*会大大增加崩溃或损坏的风险,没有明显的原因。您可能希望尽快重新考虑您的设计。

于 2014-02-27T20:16:00.567 回答
0

对于可能与您拥有的代码一起使用的快速(并且在我看来)肮脏的解决方案是复制数据,而不是覆盖指针,从而导致内存泄漏(以及使其指向的数据消失的可能性)任何时候)。

首先,不只是初始化它,而是分配内存,以后可以释放:

case BOOL_TYPE: {
    data.push_back(new bool);
    break;

然后在设置适当的数据时,首先释放现有内存,然后在设置值时重新分配它:

case BOOL_TYPE: {
    if(!isNull){
        delete data[c];
        data[c] = new bool(row[c]);
    }
}
break;
于 2014-02-27T18:56:34.473 回答