在此代码中生成分段错误的位置?

时间:2011-05-23 04:30:28

标签: c++

class Transaction  //TO store a transaction read from file
{
public:
    int maxlenth;
    int length1,length2;
    vector<string> *items;
    vector<int>  *share; 
    int tmv;

    Transaction():maxlenth(Translen),length1(0),length2(0)
    {
        items=new vector<string>(maxlenth);
        share=new vector<int>(maxlenth);
    }
    ~Transaction()    
    {
        delete items;
        delete share;
    }

    void set_tmv()
    {
        tmv=0;
        for(int i=0;i<=length2;i++)
               tmv=tmv+(*share)[i];
    }     
};


class Data
{
public:
    ifstream in;

    Data(char *filename);
    ~Data();

    Transaction& getnextTransaction(Transaction &Trans);
};


Data::Data(char *filename)
{
    ifstream in(filename);
        assure(in,filename);
}

Data::~Data()
{
    in.close(); 
}

Transaction&  Data::getnextTransaction(Transaction &Trans)
{
    const char* delimiters =
          "  \t;()\"<>:{}[]+-=&*#.,/\\~";

    //ifstream in("testdata.txt");
    //set<string>Items1;
    vector<string> v(5);
    int i=0;
    string line;
    getline(in, line); 

    char* s =strtok((char*)line.c_str(), delimiters);
    while(s) 
    {
        if(i==v.size())
            v.resize(v.size()*2);

        v[i++]=s;
        s = strtok(0, delimiters);
    }
    vector<string>::iterator it=v.begin();
    int j=0;
    while(j<50)
    {
        (*Trans.items)[(Trans.length1)++]=v[j];
        j=j+2;
    }
    j=1;
    while(j<=50)
    {
        (*Trans.share)[Trans.length2++]=(atoi(v[j].c_str()));
        j=j+2;
    }

    //copy(v.begin(),v.end(),ostream_iterator<string>(cout,"\n");
    return Trans;
}

int main()
{
    Data d("testdata.txt");
    Transaction t,q;

    d.getnextTransaction(t);
    t.set_tmv();

    return 0;
}

当我正在使用gdb进行调试时,我正在设置:

  

程序收到std :: string :: assign中的SIGSEGV分段错误(std :: string const&amp;)

虽然我在功能ifstream in("testdata.txt")中加入了行getNexttransaction(),但我没有收到任何错误。

出了什么问题?

4 个答案:

答案 0 :(得分:4)

好吧,我没有阅读你的代码所以我不知道它的目的是什么,但如果它是一个通常的c ++应用程序而没有修改系统默认内存管理,你应该学习使用GDB。

http://www.unknownroad.com/rtfm/gdbtut/gdbsegfault.html

帮助大量删除那些令人讨厌的段错误,它只需要你花5分钟阅读并使用它,但可以节省你几小时的printf调试。 (对不起,但阅读那么多代码以找到对某些内存的错误引用会很难)

答案 1 :(得分:2)

你怎么能完全确定你的向量v中有50个元素,而且数量不少?在这个while循环中,

while(j<50)
{
  (*Trans.items)[(Trans.length1)++]=v[j];
  j=j+2;
}

您正在访问向量v的最多50个成员,因为您正在拨打v[j],而j将最多访问49,但如果{{1}那么你会得到一个分段错误。由于您将v.size() != 50初始化为仅5个元素,并且仅在您增加超过当前最大大小时调整大小,这意味着v中至少有5个或更多成员,但这并不意味着将至少有50名成员。对于使用v的值的第二个while循环也是如此。

答案 2 :(得分:1)

稍微破解代码以便编译。我从valgrind得到这个:

bash> valgrind ./a.out

Invalid read of size 4
==1827==    at 0xDE038: std::string::assign(std::string const&) (in /usr/lib/libstdc++.6.0.4.dylib)
==1827==    by 0x282B: Data::getnextTransaction(Transaction&) (dummy.cpp:88)
==1827==    by 0x2947: main (dummy.cpp:110)
==1827==  Address 0x3ec6d8 is 4 bytes after a block of size 20 alloc'd
==1827==    at 0x1A6BB: operator new(unsigned long) (vg_replace_malloc.c:261)

88行就在你的主读取循环中。建议您的循环可能会混淆。

这可能不是你的问题。 (因为我必须注释掉assure来编译它,而我没有你的数据文件...)但你可以使用类似的方法来获得真正的罪魁祸首。

答案 3 :(得分:0)

编辑:(删除了有关解除引用Trans的部分)

在这种特殊情况下,

Translen可能是您的问题。如果它小于50,那么在items的{​​{1}}循环期间,您将超过sharewhile(j<50)数组的长度。杰森的回答阐述了这一点。