Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 20.06.2023, 18:35   #1
Anton911
Форумчанин
 
Аватар для Anton911
 
Регистрация: 23.08.2011
Сообщений: 171
По умолчанию Ошибка с указателем на массив (нарушение прав доступа при чтении по адресу)

Приветствую уважаемые форумчане, изучаю с++ и написал код который хорошо работает с двумерным статическим массивом (без указателей). Но всё было в одной большой функции и хотелось массив динамический, решил в учебных целях по работать с указателем и переделал код, я так понял с динамическими массивами в с++ работаем через указатели? Процедура massInitElements работает хорошо, но в функции homeWork6 возникает ошибка в строчке которая выделена красным (нарушение прав доступа при чтении по адресу).
Код:
void homeWork6() {
   const int massSize = 8; //Эта константа реликт от статических массивов, допустим я ввел с клавиатуры произвольное значение
   int** mass1 = new int* [massSize];  //Мой основной массив указателей на массив указателей на целочисленные значения (у меня двумерный массив) 
   massInitElements(mass1[0], massSize); 
   cout <<mass1[0][0];       //Почему же я не могу прочитать этот элемент? 
}


void massInitElements(int* mass, int massSize) {
   srand(time(0));  //Запускаем генератор значений 
   int** massNew = new int*[massSize]; //инициализация указателя на массив указателей
   massNew[0] = mass; //теперь указатель на указатель имеет ссылку на мой массив из аргумента процедуры
   for (int k = 0; k < massSize; k++) {
      massNew[k] = new int[massSize]; //инициализация подмассива указателей
      for (int n = 0; n < massSize; n++) {
         massNew[k][n] = rand() % 10; //забиваем рандомными значениями от 0 до 9
         printf("%2d", massNew[k][n]);
      }
      printf("\n");
   }
}
P.S. Я сознательно убрал из кода много всего, что не относится к ошибке (delete [] mass1 и все остальное), чтобы уменьшить количество кода .
Каждый день узнаю новое...

Последний раз редактировалось Anton911; 20.06.2023 в 18:55.
Anton911 вне форума Ответить с цитированием
Старый 20.06.2023, 18:46   #2
Anton911
Форумчанин
 
Аватар для Anton911
 
Регистрация: 23.08.2011
Сообщений: 171
По умолчанию

В общем я вижу что я затупил и 2 раза выделил память под массив указателей на указатели.
Первый раз в процедуре homeWork6 в строчке
Код:
int** mass1 = new int* [massSize];
А второй раз в функции massInitElements в строчке
Код:
int** massNew = new int*[massSize];
А значит ошибка возникала потому-что я инициализировал и забивал значениями один участок в памяти, а в функции homeWork6 пытался читать другой, не инициализированный участок памяти.
Но если я уберу из функции massInitElements
Код:
int** massNew = new int*[massSize];
, то вообще не компилится.
Код:
void massInitElements(int* mass, int massSize) {
   int** massNew;
   massNew[0] = mass; //В этой строчке пишет - использована неинициализированная локальная переменная "massNew"	

   for (int k = 0; k < massSize; k++) {
      massNew[k] = new int[massSize];
      for (int n = 0; n < massSize; n++) {
         massNew[k][n] = rand() % 10;
         printf("%2d", massNew[k][n]);
      }
      printf("\n");
   }
}
Как правильно сделать?
Или может быть я вообще зря полез в указатели? Грубо говоря я хочу в отдельной функции (от основной процедуры) забить значениями динамический массив. В функцию пытаюсь передать ссылку на мой массив.


Вот полный код, объединил все это в одну функцию, так работает всё.
Код:
int  homeWork6() {
   const int massSize = 8;
   int** mass1 = new int* [massSize];
   int summDiagonalElements = 0;
   srand(time(0));
   printf("Матрица:\n");
   for (int k = 0; k < massSize; k++) {
      mass1[k] = new int[massSize];
      for (int n = 0; n < massSize; n++) {
         mass1[k][n] = rand() % 10;
         printf("%2d", mass1[k][n]);
      }
      printf("\n");
   }
   cout <<mass1[0][0];
   printf("Суммирующиеся значения: ");
   for (int k = 0; k < massSize; k++) {
      for (int n = 0; n < massSize; n++) {
         if (k == n) { 
            summDiagonalElements += mass1[k][n]; 
            cout << mass1[k][n] << " ";
         }
         if ((k == massSize - 1 - n) && (n == massSize - 1 - k)) {
            summDiagonalElements += mass1[k][n];
            cout << mass1[k][n] << " ";
         }
      }
   }
   for (int k = 0; k < massSize; k++) delete[] mass1[k];
   delete [] mass1;
   
   printf("\nСумма диагональных элементов матрицы: ");
   if (massSize % 2 != 0) {
      summDiagonalElements -= mass1[massSize / 2 + 1][massSize / 2 + 1];
   }
      
   return summDiagonalElements;
}
Но как же разделить? как вынести этот код в отдельную процедуру?
Код:
 for (int k = 0; k < massSize; k++) {
      mass1[k] = new int[massSize];
      for (int n = 0; n < massSize; n++) {
         mass1[k][n] = rand() % 10;
         printf("%2d", mass1[k][n]);
      }
      printf("\n");
   }
Каждый день узнаю новое...

Последний раз редактировалось Anton911; 20.06.2023 в 19:06.
Anton911 вне форума Ответить с цитированием
Старый 20.06.2023, 19:25   #3
BDA
МегаМодератор
СуперМодератор
 
Аватар для BDA
 
Регистрация: 09.11.2010
Сообщений: 7,291
По умолчанию

Выделяйте память в одной из функций, чтобы не путаться.
Код:
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <ctime>

using namespace std;

int** massInitElements(int massSize)
{
   int** massNew = new int*[massSize];
   for (int k = 0; k < massSize; k++) {
      massNew[k] = new int[massSize];
      for (int n = 0; n < massSize; n++) {
         massNew[k][n] = rand() % 10;
         printf("%2d", massNew[k][n]);
      }
      printf("\n");
   }
   return massNew;
}

void homeWork6()
{
   const int massSize = 8;
   int** mass1 = massInitElements(massSize);
   cout << mass1[0][0] << endl;
   for (int k = 0; k < massSize; k++)
        delete[] mass1[k];
    delete[] mass1;
}

void massInitElements2(int** massNew, int massSize)
{
   for (int k = 0; k < massSize; k++) {
      for (int n = 0; n < massSize; n++) {
         massNew[k][n] = rand() % 10;
         printf("%2d", massNew[k][n]);
      }
      printf("\n");
   }
}

void homeWork62()
{
   const int massSize = 8;
   int** mass1 = new int*[massSize];
   for (int k = 0; k < massSize; k++)
      mass1[k] = new int[massSize];
   massInitElements2(mass1, massSize);
   cout << mass1[0][0] << endl;
   for (int k = 0; k < massSize; k++)
        delete[] mass1[k];
    delete[] mass1;
}


int main()
{
    srand(time(0));
    homeWork6();
    homeWork62();
    return 0;
}
Пишите язык программирования - это форум программистов, а не экстрасенсов. (<= это подпись )
BDA вне форума Ответить с цитированием
Старый 20.06.2023, 20:07   #4
Anton911
Форумчанин
 
Аватар для Anton911
 
Регистрация: 23.08.2011
Сообщений: 171
По умолчанию

BDA, спасибо большое, оба варианта работают. Не знаю как вам спасибку поставить, раньше вроде были кнопки.
Каждый день узнаю новое...
Anton911 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Массив - нарушение прав доступа при чтении по адресу 0xDD8CED4B krrinokk Помощь студентам 1 03.11.2020 00:20
Direct2D.Вызвано исключение по адресу 0x10003C66 (RTSSHooks.dll) в Win32Project1.exe: 0xC0000005: нарушение прав доступа при чтении по адресу 0x00000000. Maxim_St Win Api 1 15.04.2019 16:40
Mutex нарушение прав доступа при чтении по адресу Eugenelife Помощь студентам 0 15.12.2013 13:13
c++ нарушение прав доступа при чтении по адресу 0x00000000 proef Помощь студентам 7 05.09.2013 23:49