heap-use-after-free при объявлении переменной в качестве ссылки - PullRequest
0 голосов
/ 12 июля 2020

Вставленный ниже код возвращает ошибку heap-use-after-free. Когда я удаляю ссылочный символ '&' в строке с coord &c = q.front(); q.pop();, ошибка устраняется.

Насколько я понимаю, сборщик мусора C ++ удаляет координаты, полученные мной из q.front (), когда там больше нет ссылок на него. Хотя здесь кажется, что c в coord &c удаляется из кучи сразу после того, как он выталкивается из очереди, и попытка доступа к c в следующей строке вызывает ошибку. Однако это происходит не каждый раз, поэтому мне интересно, может ли кто-нибудь помочь мне понять, почему это происходит.

    class Solution {
    public:
        int numIslands(vector<vector<char>>& grid) {
            if(grid.size() == 0) return 0;
            typedef pair<int,int> coord;
            queue<coord> q;
            const int m = grid.size();
            const int n = grid[0].size();
            int i_in[] = {0,0,1,-1};
            int j_in[] = {1,-1,0,0};
            int ans = 0;
            for(int i = 0; i < m; ++i)
            {
                for(int j = 0; j < n; ++j)
                {
                    if(grid[i][j] == '1')
                    {
                        ++ans;
                        q.push(coord(i,j));
                        while(q.size() > 0)
                        {
                            coord &c = q.front(); q.pop();
                            grid[c.first][c.second] = '*';
                            for(int k = 0; k < 4; ++k)
                            {
                                int newi = c.first + i_in[k];
                                int newj = c.second + j_in[k];
                                if(newi >= 0 && newi < m &&
                                   newj >= 0 && newj < n && 
                                   grid[newi][newj] == '1')
                                {
                                    q.push(coord(newi, newj));
                                }
                            }
                        }
                    }
                }
            }
            return ans;
        }
    };

1 Ответ

1 голос
/ 12 июля 2020
coord &c = q.front(); 

^^^ Эта строка устанавливает c для ссылки на pair<int,int>, который в настоящее время находится в начале очереди.

q.pop();

^^^ Эта строка удаляет элемент в перед очереди, уничтожая ее в процессе). Итак, после возврата этой строки ваша ссылка c указывает на недопустимый объект, что означает, что попытка использовать c вызовет неопределенное поведение.

Однако это происходит не каждый раз, поэтому мне интересно, может ли кто-нибудь помочь мне понять, почему это происходит.

Происходит неопределенное поведение , которое вызывается, когда вы пытаетесь использовать висящую ссылку . В поведении undefined интересно то, что «кажется, что все работает нормально» является допустимым результатом, как и буквально все остальное, что происходит - потому что, как только вы вызываете поведение undefined, все ставки отключены, авторы компилятора свободны от каких-либо обязательства, чтобы программа работала правильно оттуда, и мир сломан.

Чтобы решить проблему, вы можете либо удалить амперсанд (как вы это сделали), чтобы не было ссылки, и, следовательно, нет шансов проблемы с висячими ссылками (поскольку вместо этого вы скопировали объект очереди pair<int,int> в локальную переменную); или, в качестве альтернативы, вы можете переместить свой вызов на q.pop() в конец вашего while-l oop, чтобы он происходил только после того, как все ваши использования ссылки c уже выполнены.

...