无法找到未定义行为的原因

时间:2018-06-12 09:58:31

标签: c++ global-variables undefined-behavior

在下面的程序中,我声明了一个全局变量(adj_matrix),以便在不同的函数中使用它。它在另一个函数(init_matrix)中定义。

我使用测试用例3 1 2测试了该程序并收到了分段错误。

3 1 2
YES
Segmentation fault: 11

令人惊讶的是,当我取消注释cout函数中的construct_matrix行时,分段错误消失了。

这看起来像我的未定义行为的情况,但我无法弄清楚它发生的原因和位置。请帮忙。

以下是该计划:

#include <iostream>
#include <vector>

using namespace std;

vector<vector<int> > adj_matrix;

void init_matrix(int size, int val)
{
    adj_matrix.reserve(size);
    for (int i = 0; i < size; ++i)
    {
        adj_matrix[i].reserve(size);
        for (int j = 0; j < size; ++j)
        {
            if(i == j)
                adj_matrix[i][i] = 0;
            else
                adj_matrix[i][j] = val;
        }
    }
}

void construct_matrix(int size, int k, int val)
{
    // k denotes how many components we want
    for (int i = k - 1; i < size - 1; ++i)
    {
        adj_matrix[i][i + 1] = val;
        adj_matrix[i + 1][i] = val;
        // Uncommenting the following line resolves the seg-fault error
        // cout << i << endl;
    }
}

void print_matrix(int size)
{
    for (int i = 0; i < size; ++i)
    {
        for (int j = 0; j < size; ++j)
            cout << adj_matrix[i][j];
        cout << endl;
    }
}

int main()
{
    int n, a, b;
    cin >> n >> a >> b;

    /*
    The solution uses the fact that atleast one of G or G complement is always connected.
    In cases where we have to show both are connected (not possible when n is 2 or 3), 
    we draw a simple graph connected v1 v2 v3...vn. The complement will be also connected (n != 2 and 3)
    */

    if(a == 1 && b == 1)
    {
        if(n == 2 || n == 3)
            cout << "NO" << endl;
        else
        {
            cout << "YES" << endl;
            init_matrix(n, 0);
            construct_matrix(n, 1, 1);
            print_matrix(n);
        }
    }
    else if(a == 1)
    {
        cout << "YES" << endl;
        init_matrix(n, 1);
        construct_matrix(n, b, 0);

        print_matrix(n);

    }
    else if(b == 1)
    {
        cout << "YES" << endl;
        init_matrix(n, 0);
        construct_matrix(n, a, 1);
        print_matrix(n);

    }
    else
        cout << "NO" << endl;

    return 0;
}

对于对此问题感兴趣的人,这是一个解决方案,请访问here

PS:我已经检查了我的函数中for循环中的边界,它们是正确的。如果情况并非如此,则无论cout行如何,程序都会抛出分段错误。

2 个答案:

答案 0 :(得分:2)

此代码中未定义行为的原因/原因之一是使用operator[]来访问尚未创建的向量元素。

来自http://www.cplusplus.com/reference/vector/vector/operator[]/

  

类似的成员函数vector :: at与此操作符函数具有相同的行为,除了对vector :: at进行绑定检查,并通过抛出out_of_range异常来通知请求的位置是否超出范围。

     

可移植程序永远不应该使用超出范围的参数n来调用此函数,因为这会导致未定义的行为。

reserve不会创建向量的新元素。它只是确保向量为它们分配了足够的内存。如果要创建可以访问的新元素,请使用resize。 (https://stackoverflow.com/a/7397862/3052438

我还建议您在解决第一个问题后仔细检查所有向量访问是否超出绑定索引。

答案 1 :(得分:1)

your_action: handler: path/lambda_function.handler 不创建任何元素,只保留向量的大小。因此,当adj_matrix.reserve(size);大于adj_matrix[i].reserve(size);

时,i是未定义的行为