字符串函数参数的分段错误

segmentation fault for string function argument

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

  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 ;
}
char str[100000000];

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

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

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

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