Проблема динамического многомерного массива C

#c #multidimensional-array #dynamic-arrays

#c #многомерный массив #динамические массивы

Вопрос:

Я разрабатываю 2d-платформер. Все было хорошо, пока у меня не возникла трудноразрешимая проблема. Карта уровней хранится в динамическом многомерном массиве (char **map). Это работает нормально, пока я не захочу переопределить это

Вот часть кода:

 Mapamp; Map::operator=(const Mapamp; rhs)
{
    if(width!=0||height!=0)
    {
        for(int i=0;i<width;i  )
            delete[] map[i];
        delete[] map;
    } //deleting previously created array

    height=rhs.height;
    width=rhs.width; //receiving other map's size

    map=new char* [width];
    walkmap=new unsigned char* [width];
    objmap=new char* [width];
    for(int i=0;i<width;i  )
    {
        *(map i)=new char[height];
    } //creating new array

    for(int h=0;h<height;h  )
        for(int w=0;w<width;w  )
        {
            map[w][h]=rhs.map[w][h];
        } //receiving new values

    //...
}
  

В первый раз все работает нормально, но когда мне нужно переопределить массив во второй раз, моя программа вылетает в той части, когда массив получает новые значения от другого. Может быть, я что-то пропустил, но я не могу это найти! Я искал эту проблему, но не нашел, что я делаю неправильно. Помогите мне, пожалуйста.

Комментарии:

1. Вы пропустили объявление типа (def?) Map , что довольно важно для вопроса.

2. Также я бы изменил *(map i) на map[i] только потому, что это гораздо более описывает то, чего вы пытаетесь достичь с помощью этой строки, ИМХО.

Ответ №1:

Как всегда, Boost имеет элегантный класс многомерных массивов, экономящий память:

 http://www.boost.org/doc/libs/1_39_0/libs/multi_array/doc/user.html
  

Например, для настройки массива значений bool размером 10 x 20:

  
    boost::multi_array  mtaFlagMatrix(boost::extents[10][20]);
   

Затем для доступа к его элементам:

  
    mtaFlagMatrix[2][6] = false; // indexes are zero-based - just like normal C arrays
     ...
    if ( mtaFlagMatrix[2][6] )
    {
       ...
    }
   

Затем вы можете изменить размер массива таким образом (существующие значения сохраняются):

  
typedef boost::multi_array array_type;

array_type::extent_gen extents; array_type A(extents[3][3][3]); A[0][0][0] = 4; A[2][2][2] = 5; A.resize(extents[2][3][4]); assert(A[0][0][0] == 4); // A[2][2][2] is no longer valid.

Это сэкономило мне много времени на тестирование для крайних случаев.

Комментарии:

1. О, я не хочу использовать дополнительные компоненты, потому что мой код будет трудно понять. Мне не нужно менять размер очень часто. Всего 2 или 3 раза! И использование библиотек не поможет мне понять, когда я был неправ, D:

Ответ №2:

Ваш 2d-массив не освобожден должным образом. Я советую вам использовать способ Iliffe для выделения 2d-массивов, который быстрее и безопаснее в использовании:

 char** alloc_array( int h, int w )
{
  typedef char* cptr;
  int i;
  char** m = new cptr[h];
  m[0] = new char[h*w];
  for(i=1;i<h;i  ) m[i] = m[i-1] w;
  return m;
}

void release_array(char** m)
{
  delete[] m[0];
  delete[] m;
}

int main()
{
  int r,c;
  char** tab;
  int width  = 5;
  int height = 3;
  tab = alloc_array(height, width); /* column first */

  for(r = 0;r<height;  r)
   for(c = 0;c<width;  c)
    tab[r][c] = (1 r c);

  for(r = 0;r<height;  r)
  {
    for(c = 0;c<width;  c)
    {
      printf("%dt",tab[r][c]);
    }
    puts("");
  }
  release_array(tab);
}
  

Это можно легко инкапсулировать в аккуратный класс 2d-массива или заставить использовать std::vector вместо необработанного выделения. Предпочитаю этот способ создания 2d-массива, поскольку он удобен для кэширования, обеспечивает доступ к [][] и работает не медленнее, а иногда и быстрее, чем полиномиальный одномерный доступ.

Комментарии:

1. Спасибо, я попробую использовать этот метод

2. Ого, та же проблема. В первый раз все работает нормально, затем я удаляю ранее созданный массив, создаю новый массив (теперь все в порядке), но когда я начинаю присваивать некоторые новые значения новому массиву, программа снова вылетает, то же самое происходит в моем коде.

3. вы делаете что-то неправильно в другом месте. можете ли вы показать мне свой обновленный код для обозначения этих функций

4. pastebin.com/Gtvnf2wA Вот она. (В первый раз rhs.tileset!=0, но во второй раз это 0

5. О, и другие массивы используют тот же метод (но это не показано в коде)