Ошибка Valgrind в трехмерном массиве C ++ - PullRequest
0 голосов
/ 23 мая 2018

У меня проблемы с пониманием ошибки Valgrind, отображаемой при компиляции программы на C ++ для создания и управления трехмерным массивом.

Я запрограммировал программное обеспечение на своем Mac, и все выглядело нормально, но когда я портировал его на Ubuntu, я не только получаю ошибку Valgrind, но и вывод (и неверный) выводится на Mac.

Вот ошибка Valgrind:

==10705== Invalid write of size 4
==10705==    at 0x401095: Matrice3D<int>::Matrice3D(unsigned int, unsigned int, unsigned int, int const&) (in /media/psf/sharedFolder/Progetto_2/main.exe)
==10705==    by 0x400BE1: main (in /media/psf/sharedFolder/Progetto_2/main.exe)
==10705==  Address 0x5ab6e10 is 0 bytes after a block of size 192 alloc'd
==10705==    at 0x4C2E80F: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==10705==    by 0x40102E: Matrice3D<int>::Matrice3D(unsigned int, unsigned int, unsigned int, int const&) (in /media/psf/sharedFolder/Progetto_2/main.exe)
==10705==    by 0x400BE1: main (in /media/psf/sharedFolder/Progetto_2/main.exe)
==10705== 
--10705-- VALGRIND INTERNAL ERROR: Valgrind received a signal 11 (SIGSEGV) - exiting
--10705-- si_code=1;  Faulting address: 0x1105AB6E38;  sp: 0x802ca9e30

и указанный конструктор:

Matrice3D(unsigned int height, unsigned int width, unsigned int depth, const T &value) : _3D_matrix(0), _height(0), _width(0), _depth(0) { 

    try {
       _3D_matrix = new T[height * width * depth];
            for (int z = 0; z < depth; z++) {
                for (int j = 0; j < height; j++) {
                    for (int k = 0; k < width; k++) {
                        _3D_matrix[j * height * depth + k * depth + z] = value; 
                    }
                }
            }
   }
    catch(...) {
        delete[] _3D_matrix;
        throw;
    }


    _height = height;
    _width = width;
    _depth = depth;

    }

У кого-нибудь был подобный опыт?Я делаю что-то неправильно?Заранее спасибо!

Ответы [ 2 ]

0 голосов
/ 23 мая 2018

Ваш расчет индекса неверен.

z идет от 0 до depth.
j идет от 0 до height.
kидет от 0 до width.

Пока все хорошо (ну, j и k вместо x и y необычны и, вероятно, являются хорошей частью путаницы),Но:

_3D_matrix[j * height * depth + k * depth + z] = value;

Умножение j на height является ошибкой, вероятно, должно быть width.
Рассмотрим этот случай: j = height - 1, k = 0, z = 0.Тогда ваш индекс будет height * depth * (height - 1), что, очевидно, неверно, если height отличается от width.

Хитрость в отладке таких случаев, когда вы не уверены в индексах массива, заключается в рассмотрении крайних случаев.Если вы подумаете о вышеупомянутом случае (или случае, когда все переменные цикла максимальны), вы сразу увидите, что ваш индекс может превышать размер вашего массива.

0 голосов
/ 23 мая 2018

Похоже, что проблема с записью вызвана смешиванием диапазонов / индексацией различных for уровней:

_3D_matrix[j * height * depth + k * depth + z] = value;

Посмотрите здесь: https://ideone.com/gkUXib - ваш код перемещен вавтономная функция с добавленным индексным выходом.Выходные данные показывают, что некоторые индексы назначаются дважды (например, 22 в примере), некоторые остаются никогда не назначенными (например, 63).Порядок индексов выглядит странно, из-за чего трудно рассуждать.

Возможно, некоторая комбинация ширины, высоты и глубины может вызвать ошибку, как вы заметили.

Я бы порекомендовал упроститьпеременные fors («строка» означает строку, а не что-то другое), используйте std::array или просто используйте массив одного измерения и самостоятельно реализуйте строки, столбцы и глубину.

...