簡體   English   中英

向量序列化/反序列化中的C ++分段錯誤

[英]C++ Segmentation Fault in vector serialize/deserialize

請幫我調試下面的代碼。 我正在做的只是將vector<string>序列化為二進制文件並從中檢索它。 這是示例主代碼,

    /*  Portion Commented */
vector<string> list;

list.push_back("AAAAAA");
list.push_back("BBBBBB");
list.push_back("CCCCCC");
list.push_back("DDDDDD");

// Write out a list to a disk file
ofstream os ("/home/test/data.dat", ios::binary);

int size1 = list.size();
os.write((const char*)&size1, sizeof(int));
os.write((const char*)&list[0], size1 * sizeof(string));
os.close();
/* Portion Commented */

// Read it back in
VertexList list2;

ifstream is("/home/test/data.dat", ios::binary);
int size2;
is.read((char*)&size2, sizeof(int));

list2.resize(size2);
cout<<"Size is :"<<size2<<endl;
is.read((char*)&list2[0], size2 * sizeof(string));
for (int i=0; i < size2; i++)
{
        cout<<"At i = "<<i<<", "<<list2[i]<<endl;   //Line 40 in my program
}

我有4個元素被推入矢量列表。 然后我序列化向量並將其寫入二進制文件並從中檢索回來。 它工作正常。

后來當我在上面的代碼中評論'Portion Commented'並試圖直接從已經創建的二進制文件“data.data”中檢索向量時,它顯示了分段錯誤事件,盡管它在for循環之前正確地打印了4的大小。 這是我用這個創建的valgrind輸出( valgrind --leak-check=yes ./a.out ),

==14058== Invalid read of size 8  
==14058==    at 0x4EBE263: std::basic_ostream<char, std::char_traits<char> >& std::operator<< <char, std::char_traits<char>, std::allocator<char> >(std::basic_ostream<char, std::char_traits<char> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (in /usr/lib/libstdc++.so.6.0.14)  
==14058==    by 0x40107F: main (test2.cpp:40)  
==14058==  Address 0x2156010 is not stack'd, malloc'd or (recently) free'd 

第40行是最后一個for循環中的cout語句。 有人可以幫我調試嗎? 還告訴我上面的代碼是否可移植?

謝謝,Prabu

std::string的實現包括指向堆上實際字符串內容的指針。 因此, sizeof(string)只是指針加上一些字節。 如果要編寫字符串,則必須自己編寫內容

for (auto i = list.begin(); i != list.end(); ++i) {
    os.write(i->c_str(), i->size() + 1);
}

當您重讀時,必須查找終止NUL字節。 或者,您可以像保存列表一樣保存字符串的長度

for (auto i = list.begin(); i != list.end(); ++i) {
    int len = i->size() + 1;
    os.write((const char*)&len, sizeof(len));
    os.write(i->c_str(), i->size() + 1);
}
os.write((const char*)&list[0], size1 * sizeof(string));

你在這里做什么? std::string轉換為const char* 這沒有意義。

如果您使用C ++樣式轉換,編譯器將告訴您為什么它沒有意義。 這就是為什么C ++程序員應該避免使用C風格的演員!

你可能想做的是:

os.write(list[0].c_str(), list[0].size() + 1);

你應該在一個循環中這樣做:

for(auto const & s : list) //s is inferred to be std::string
{
  os.write(s.c_str(), s.size() + 1);
}

在C / C ++中,您不應該保存序列化的結構或類,除非您知道實現並且沒有指針。
更好的方法是使用boost序列化。 他們已經做了一切來支持序列化/反序列化STL對象。

#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/serialization/string.hpp>
#include <boost/serialization/vector.hpp>
#include <iostream>
#include <vector>
#include <fstream>
#include <string>
using namespace std;
int main(int ac, char **av)
{
    vector<string> list1;

    list1.push_back("AAAAAA");
    list1.push_back("BBBBBB");
    list1.push_back("CCCCCC");
    list1.push_back("DDDDDD");

    // Write out a list to a disk file
    ofstream os ("data.dat", ios::binary);

    boost::archive::binary_oarchive oa(os);
    oa << list1;
    os.close();

    vector<string> list2;

    ifstream is("data.dat", ios::binary);
    boost::archive::binary_iarchive ia(is);
    ia >> list2;
    int size2 = list2.size();
    for (int i=0; i < size2; i++)
    {
       cout<<"At i = "<<i<<", "<<list2[i]<<endl;   //Line 40 in my program
    }
}

sizeof( std::string )給出了string對象的大小。 實際的字符串數據本身是動態的,並由string類中的指針保存。

您可能希望使用google協議緩沖區boost序列化來序列化/反序列化對象。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM