将sparse_hash_map <char * const,=“”int =“”>序列化为文件时出现问题

时间:2015-05-28 16:53:03

标签: c++ serialization

这是我将sparse_hash_map(char * const,int)序列化为文件的代码,注意map.key类型是char *const,这是必需的(如果没有,编译器报告没有找到匹配的函数)。发生问题的地方,因为我无法将内存分配给char *const类型的变量,如何在为其分配足够的内存之前将序列化文件中的数据读入map.key?或者,有什么方法可以序列化除此之外的sparse_hash_map(char * const,int)吗?

#include <iostream>
#include <sparsehash/sparse_hash_map>
using google::sparse_hash_map;      // namespace where class lives by default

using namespace std;

#define SIZE 13

struct CharPointerToIntSerializer {
  bool operator()(FILE* fp, std::pair<char * const, int>* value) const {
    // this can't be done, since value->first is of type 'char *const'
    // value->first = realloc(value->first, SIZE);
    if (fread(const_cast<char *>(value->first), 1, SIZE, fp) != 1) {
      return false;
    }

    if (fread(&(value->second), sizeof(value->second), 1, fp) != 1)
      return false;
    return true;
  }

  bool operator()(FILE* fp, const std::pair<char * const, int>& value) const {
    if (fwrite(value.first, 1, SIZE, fp) != 1)
      return false;

    if (fwrite(&value.second, sizeof(value.second), 1, fp) != 1)
      return false;
    return true;
  }
};

int main(){
  sparse_hash_map<char*, int> old_map,new_map;
  char *p1, *p2;
  p1 = (char *) malloc(SIZE);
  p2 = (char *) malloc(SIZE);
  strcpy(p1, "hello");
  strcpy(p2, "world");
  old_map[p1] = 1;
  old_map[p2] = 2;

  FILE* fp = fopen("hashtable.txt", "w");
  old_map.serialize(CharPointerToIntSerializer(), fp);
  // cout << old_map[p1] << endl;
  // cout << old_map[p2] << endl;
  fclose(fp);

  FILE* fp_in = fopen("hashtable.txt", "r");
  new_map.unserialize(CharPointerToIntSerializer(), fp_in);
  fclose(fp_in);
  assert(old_map == new_map);
  cout << new_map[p2] << endl;
}

这个程序编译,但是当我运行它时,它告诉我&#34;分段错误11&#34;和gdb调试结果说&#34; memcpy.S:没有这样的文件或目录&#34;,任何帮助将不胜感激! :)

1 个答案:

答案 0 :(得分:0)

回答OP关于char *的问题,首先是真的那么糟糕。

与std :: string相比,

char *会大大增加您的工作量。首先,不需要mallocfree(顺便说一句,你不是free)。尺寸和尺寸调整是为您完成的。实际上,除非您使用指向std :: strings的指针,否则将为您处理所有内存管理。 strcpy以及随之而来的所有超限检查都会变为=。如果您需要,可以直接构建拆分,搜索和排序功能。非常方便的小家伙,std :: strings。

作为容器键,您可能无法控制销毁逻辑。该对将被销毁,指针将随之被销毁,但指向的内存仍然存在,需要free d,但你不再有一个指针可以调用{{1 }}

你可以在对的析构函数触发并销毁指针之前free内存,但是你必须保护代码中你销毁一对的所有点。为什么可以为你完成程序中的头痛和跟踪代码?

问题

free

正如您所指出的,您无法为bool operator()(FILE* fp, std::pair<char * const, int>* value) const { // this can't be done, since value->first is of type 'char *const' // value->first = realloc(value->first, SIZE); if (fread(const_cast<char *>(value->first), 1, SIZE, fp) != 1) { return false; } if (fread(&(value->second), sizeof(value->second), 1, fp) != 1) return false; return true; } 分配存储空间,因此除非您在首次创建该对时为value->first分配了存储空间,否则fread(const_cast<char *>(value->first), 1, SIZE, fp)将会注定失败。如果你没有创建该对,那么value->first指向NULL的几率非常高。 fread to NULL变得繁荣。

接下来,当地图删除该对时,谁value->first是char *?可能是内存泄漏。

问题随着字符串的消失而消失,但你不想直接进入字符串。

你会想要更像

的东西
free

Buf在堆栈上分配,因此当它超出范围时会被销毁,但到那时它已被复制到字符串中。如果使用保证的null存储,则可能不需要使用null。

错误消息“memcpy.S:没有这样的文件或目录”是GDB试图显示失败的行并且无法找到包含memcpy函数的源文件。段错误值得担心,源文件丢失,不是那么重要。该bug在调用memcpy之前的某个地方。检查堆栈跟踪以找到最后一行代码并开始在那里进行调查。