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

where the segmentation fault is generated in this code?

本文关键字:分段 错误 位置 代码      更新时间:2023-10-16
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(std::string const &( 中收到 SIGSEGV 分段错误

当我在函数getNexttransaction()中包含行ifstream in("testdata.txt")时,我没有收到任何错误。

出了

什么问题?

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

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

对消除那些讨厌的段错误有很大帮助,只需 5 分钟即可阅读和使用它,但可以节省您数小时的 printf 调试时间。(抱歉,通读这么多代码以找到对某些内存的错误引用将是一项艰巨的工作(

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

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

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

在对

代码进行一些黑客攻击以便进行编译之后。我从瓦尔格林德那里得到这个:

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才能编译它,而且我没有你的数据文件......但是你可以使用类似的方法来获得真正的罪魁祸首。

编辑:(删除了关于取消引用的部分 Trans (

在这种特殊情况下,Translen可能是您的问题。如果小于 50,您将在 getnextTransaction 中的while(j<50)循环期间超过 itemsshare数组的长度。杰森的回答详细阐述了这一点。