将 sparse_hash_map<char *const, int> 序列化到文件时出现问题
problems when I serialize sparse_hash_map<char *const, int> into file
这是我将 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;
}
这个程序可以编译,但是当我 运行 它时,它告诉我 "segmentation fault 11",并且 gdb 调试结果显示 "memcpy.S: No such file or directory",任何帮助将不胜感激! :)
首先回答 OP 关于 char * 真的那么糟糕的问题。
char * 与 std::string 相比会大大增加您的工作量。首先,不需要 malloc
和 free
(顺便说一句,你没有做 free
)。调整大小和调整大小是为您完成的。事实上,除非您使用指向 std::string 的指针,否则所有内存管理都会为您处理。 strcpy
并且随之而来的所有超限检查变为 =
。如果需要,拆分、搜索和排序功能都是内置的。非常灵巧的小家伙们,std::strings.
作为容器密钥,您可能无法控制销毁逻辑。该对将被销毁,指针将随之销毁,但指向的内存仍将存在并且需要 free
d,但您不再拥有可以调用 [=13] 的指针=].
您可以 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
分配存储空间。如果您没有创建该对,则 value->first
指向 NULL 的可能性非常大。 fread 为 NULL 会繁荣。
接下来,当映射删除该对时,free
谁是 char*?可能是内存泄漏。
问题随字符串一起消失,但您不想直接 fread 到字符串中。
你会想要更像
char buf[size+1]; // +1 for null char
int len = fread(buf, 1, SIZE, fp)
if (len != 1) {
return false;
}
buf[len] = '0\'; //terminate string with null
value->first = buf;
Buf 分配在堆栈上,因此当它超出范围时它将被销毁,但此时它已被复制到字符串中。如果 buf 以保证为 null 的方式存储,则您可能不需要 null buf。
错误消息"memcpy.S: No such file or directory" 是GDB 试图显示失败的行,但无法找到包含memcpy 函数的源文件。段错误值得担心,源文件丢失,不是那么重要。该错误出现在调用 memcpy 之前的某处。检查堆栈跟踪以找到您的最后一行代码并从那里开始调查。
这是我将 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;
}
这个程序可以编译,但是当我 运行 它时,它告诉我 "segmentation fault 11",并且 gdb 调试结果显示 "memcpy.S: No such file or directory",任何帮助将不胜感激! :)
首先回答 OP 关于 char * 真的那么糟糕的问题。
char * 与 std::string 相比会大大增加您的工作量。首先,不需要 malloc
和 free
(顺便说一句,你没有做 free
)。调整大小和调整大小是为您完成的。事实上,除非您使用指向 std::string 的指针,否则所有内存管理都会为您处理。 strcpy
并且随之而来的所有超限检查变为 =
。如果需要,拆分、搜索和排序功能都是内置的。非常灵巧的小家伙们,std::strings.
作为容器密钥,您可能无法控制销毁逻辑。该对将被销毁,指针将随之销毁,但指向的内存仍将存在并且需要 free
d,但您不再拥有可以调用 [=13] 的指针=].
您可以 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
分配存储空间。如果您没有创建该对,则 value->first
指向 NULL 的可能性非常大。 fread 为 NULL 会繁荣。
接下来,当映射删除该对时,free
谁是 char*?可能是内存泄漏。
问题随字符串一起消失,但您不想直接 fread 到字符串中。
你会想要更像
char buf[size+1]; // +1 for null char
int len = fread(buf, 1, SIZE, fp)
if (len != 1) {
return false;
}
buf[len] = '0\'; //terminate string with null
value->first = buf;
Buf 分配在堆栈上,因此当它超出范围时它将被销毁,但此时它已被复制到字符串中。如果 buf 以保证为 null 的方式存储,则您可能不需要 null buf。
错误消息"memcpy.S: No such file or directory" 是GDB 试图显示失败的行,但无法找到包含memcpy 函数的源文件。段错误值得担心,源文件丢失,不是那么重要。该错误出现在调用 memcpy 之前的某处。检查堆栈跟踪以找到您的最后一行代码并从那里开始调查。