【问题标题】:segmentation fault for string function argument字符串函数参数的分段错误
【发布时间】:2015-08-04 05:37:34
【问题描述】:

我有一个简单的主代码,在调用函数时会出现分段错误。在下面的代码中,我有两个功能,第一个可以正常工作,但程序没有进入第二个并给我分段错误错误。有什么理由吗?我已经确定了以下几点:

  1. 变量oc 没有越界。
  2. cn 已正确初始化。
  3. 我拥有cmargv 的只读访问权限。加上它甚至没有进入函数evaluate

代码如下:

void print_cm(vector<vector<int> > *cm, char* gtf);                                                                                                        
void evaluate(vector<vector<int> > *cm, char* gtf);

int main(int argc, char** argv)
{
    int o = 2; // It is initialized
    int c = 4; // It is initialized
    vector<vector<int> > cm; // It is initialized
    if (argc>4)
        print_cm(&cm, argv[o]);
    if (argc>4)
    {
        cout << argv[c] << endl; // Works
        // The following also works
        for (int i=0; i<cm.size(); i++)
            for (int j=0; j<cm[i].size(); j++)
                 cout << cm[i][j] << " ";
        // The following causes segmentation fault;
        evaluate(&cm, argv[c]);
    }
    return 0;
}

void evaluate(vector<vector<int> > *cm, char* gtf)
{
    // Read-only access to cm and gtf
}

void print_cm(vector<vector<int> > *cm, char* gtf)
{
    // Read-only access to cm and gtf
}

完整代码如下:

#include "includes/Utility.h"
#include "includes/Graph.h"


void print_cm(vector<vector<int> > *cores, char* output);
void evaluate(vector<vector<int> > const *cm, char* gtf);

int main(int argc, char** argv)
{
    int g = -1, c = -1, o = -1;
    for (int i=1; i<argc-1; i++) 
        if (argv[i][0]=='-')
        {
            if (argv[i][1]=='g')
                g = i + 1;
            else if (argv[i][1]=='c')
                c = i + 1;
            else if (argv[i][1]=='k')
                ki = i + 1;
            else if (argv[i][1]=='s')
                si = i + 1;
            else if (argv[i][1]=='o')
                o = i + 1;
        }
    Graph G;
    if (c>0) G.read_input(argv[g], argv[c]);
    else G.read_input(argv[g]);
    if (ki > 0) 
    {
        int k = atoi(argv[ki]);
        cout << k << endl;
    }
    if (si > 0) 
    {
        int s = atoi(argv[si]);
        cout << s << endl;
    }

    // Find communities
    vector<vector<int> > cores;
    G.partitioning(&cores);
    if (o>0) 
        print_cm(&cores, argv[o]);
        if (c>0) 
        {
            cout << "here" << endl;
            for (size_t i=0; i<cores.size(); i++)
                for (size_t j=0; j<cores[i].size(); j++)
                    if (cores.at(i).at(j)<0) cout << "here";
            cout << "here" << endl;
            evaluate(&cores, argv[c]);
        }
    }

    return 0;
}


void print_cm(vector<vector<int> > *cores, char* output)
{

    ofstream out;
    out.open(output);
    for(size_t i=0; i<(*cores).size(); i++)
    {
        for(size_t j=0; j<(*cores)[i].size(); j++)
            out << (*cores)[i][j] << " ";
        out << endl;
    }
    out.close();

    return ;
}

void evaluate(vector<vector<int> > const *cm, char* gtf)
{
    // we evaluate precision, recall, F1 and F2
    vector<vector<int> > gt;
    ifstream in;
    char str[100000000];
    in.open(gtf);
    while(in.getline(str, 100000000))
    {
        stringstream s;
        s << str;
        int a;
        gt.resize(gt.size()+1);
        while (s >> a) gt[gt.size()-1].push_back(a);
    }
    in.close();

    cout << "==================== Evaluation  Results ====================" << endl;
    int imax = 0;
    for(size_t i=0; i<(*cm).size(); i++)
        imax = max(imax, *max_element((*cm)[i].begin(), (*cm)[i].end()));

    for(size_t i=0; i<gt.size(); i++)
        imax = max(imax, *max_element(gt[i].begin(), gt[i].end()));

    vector<bool> flag(imax, false);
    vector<double> recall((*cm).size(), 0), precision((*cm).size(), 0), f1((*cm).size(), 0), f2((*cm).size(), 0);
    int overlap;
    double size = 0;
    for(size_t i=0; i<(*cm).size(); i++)
    {
        // evaluate
        size += (double) (*cm)[i].size();
        for(size_t j=0; j<(*cm)[i].size(); j++)
            flag[(*cm)[i][j]] = true;

        double p, r, ff1, ff2;
        for(size_t j=0; j<gt.size(); j++)
        {
            overlap = 0;
            for(size_t k=0; k<gt[j].size(); k++)
                if (flag[gt[j][k]]) overlap++;

            p = (double) overlap / (double) (*cm)[i].size();
            if (p > precision[i])
                precision[i] = p;

            r = (double) overlap / (double) gt[j].size();
            if (r > recall[i])
                recall[i] = r;

            ff1 = (double) 2*(p*r)/(p+r);
            if (ff1 > f1[i])
                f1[i] = ff1;

            ff2 = (double) 5*(p*r)/(4*p + r);
            if (ff2 > f2[i])
                f2[i] = ff2;
        }

        for(size_t j=0; j<(*cm)[i].size(); j++)
            flag[(*cm)[i][j]] = false;
    }

    double Recall = 0, Precision = 0, F1 = 0, F2 = 0;
    for(size_t i=0; i<(*cm).size(); i++)
    {
        Recall += recall[i];
        Precision += precision[i];
        F1 += f1[i];
        F2 += f2[i];
    }
    cout << "+--------------+--------------+--------------+--------------+" << endl;
    cout << "|  " << setiosflags( ios::left ) << setw(10) << "Precision";
    cout << "  |  " << setiosflags( ios::left ) << setw(10) << "Recall";
    cout << "  |  " << setiosflags( ios::left ) << setw(10) << "F1-measure";
    cout << "  |  " << setiosflags( ios::left ) << setw(10) << "F2-measure";
    cout << "  |" << endl;
    cout << "|  " << setiosflags( ios::left ) << setw(10) << Precision/(*cm).size() ;
    cout << "  |  " << setiosflags( ios::left ) << setw(10) << Recall/(*cm).size();
    cout << "  |  " << setiosflags( ios::left ) << setw(10) << F1/(*cm).size();
    cout << "  |  " << setiosflags( ios::left ) << setw(10) << F2/(*cm).size();
    cout << "  |" << endl;
    cout << "+--------------+--------------+--------------+--------------+" << endl;
    cout << "Number of communities: " << (*cm).size() << endl;
    cout << "Average community size: " << size/(*cm).size() << endl;

    return ;
}

【问题讨论】:

  • 使用调试器找出你的错误。在这种情况下,调试器应该是你的朋友和向导。
  • 所以我们应该相信你的话 // Read-only access to cm and gtf 没有做任何愚蠢的事情,或者你正在向程序传递正确数量的参数?
  • 请发MCVE
  • 如果在这些函数中有只读访问权限......那你为什么不使用指向 const 向量的指针呢?
  • @user657267 首先,第一个函数运行良好。其次,我可以在if 语句中的函数调用之前打印结果

标签: c++ segmentation-fault


【解决方案1】:
char str[100000000];

这是在您的 evaluate 函数中。这是 1 亿字节,即您在堆栈上分配的大约 95 MB。

典型的堆栈大小远小于此,大约 1 MB。

所以除了可能的其他问题之外,这很可能导致堆栈溢出。

进入函数时,堆栈帧被扩展为足够大以容纳局部变量。一旦使用堆栈(写入默认值),您将访问无效(非堆栈,幸好受保护)内存。

【讨论】:

  • 没错,这就是它的原因。为什么它不进入函数呢?
  • 这个错误很可能是在为函数构建堆栈帧的过程中,即正是在输入函数时。
猜你喜欢
  • 2013-04-16
  • 2021-09-20
  • 2012-03-28
  • 2013-05-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多