Форум программистов, компьютерный форум CyberForum.ru

memcpy/CopyMemory + 2-мерный динамический массив - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 42, средняя оценка - 4.90
_lacrimosa_
1 / 1 / 0
Регистрация: 10.06.2010
Сообщений: 26
10.06.2010, 01:02     memcpy/CopyMemory + 2-мерный динамический массив #1
Третий день в ступоре из-за ругательства компилятора. Есть проблема: нужно скопировать данные из одного двумерного динамического массива в другой. Создаю массив C(5 на 5) из нулей. Создаю массив D(5 на 5) из чисел от 1 до 25. Далее копирую из D в C все данные посредством memcpy (или CopyMemory). В итоге ошибка:"Attempt to access 100 byte(s) at 0x0106D858, that is at heap block 0x0106D858 which is only 20 bytes long."

Причём откуда 20 byte неясно - как буд-то максимум доступна 1 строка матрицы (20 байт). C и D явно занимают по 100 байт.

Функция без сбоев работает на одномерном динамическом массиве, а также статическом двумерном.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
    int NUM = 5; float x = 1;
    float** C = new float* [NUM];
 
    for (int i = 0; i < NUM; i++)
        C[i] = new float [NUM];
 
    for (int i = 0; i < NUM; i++)
        for (int j = 0; j < NUM; j++)
            C[i][j] = 0;
 
    float** D = new float* [NUM];
 
    for (int i = 0; i < NUM; i++)
        D[i] = new float [NUM];
 
    for (int i = 0; i < NUM; i++)
        for (int j = 0; j < NUM; j++)
            D[i][j] = x++;
           
    int K = NUM*NUM*sizeof(float);
    memcpy(C,D,K); //либо так: CopyMemory(C,D,K);
 
    for (int i = 0; i < NUM; i++)
        delete[] C[i];
    delete [] C;
 
    for (int i = 0; i < NUM; i++)
        delete[] D[i];
    delete [] D;
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Lord_Voodoo
Супер-модератор
 Аватар для Lord_Voodoo
8501 / 2168 / 61
Регистрация: 07.03.2007
Сообщений: 10,836
Завершенные тесты: 1
10.06.2010, 01:06     memcpy/CopyMemory + 2-мерный динамический массив #2
_lacrimosa_, сдается мне, что в данном случае надо построчно делать копирование
_lacrimosa_
1 / 1 / 0
Регистрация: 10.06.2010
Сообщений: 26
10.06.2010, 01:15  [ТС]     memcpy/CopyMemory + 2-мерный динамический массив #3
Я также начал подозревать, что для n-мерных не работает. А если массив 1000х1000х1000, то нужно пройтись по 1000*1000 строк и каждую копировать? - где тогда эффективность функции копирования памяти. Так как n-мерные представляются одномерными на непрерывном участке памяти, то по идее всё должно работать с этой функцией.

К слову, на Delphi CopyMemory работает как надо (массивы 2-мерн.динамич.)
Lord_Voodoo
Супер-модератор
 Аватар для Lord_Voodoo
8501 / 2168 / 61
Регистрация: 07.03.2007
Сообщений: 10,836
Завершенные тесты: 1
10.06.2010, 01:26     memcpy/CopyMemory + 2-мерный динамический массив #4
_lacrimosa_, я просто не уверен, что память в таком выделении идет непрерывно, да и с дельфи си равнять не стоит... хотя вы можете calloc-ом сразу выделять память и инициализировать 0-лями
_lacrimosa_
1 / 1 / 0
Регистрация: 10.06.2010
Сообщений: 26
10.06.2010, 11:33  [ТС]     memcpy/CopyMemory + 2-мерный динамический массив #5
Цитата Сообщение от Lord_Voodoo Посмотреть сообщение
я просто не уверен, что память в таком выделении идет непрерывно
хм, может действительно так и есть.

Значит calloc-ом можно сразу построить 2-мерный динамический массив в непрерывном участке памяти?
kazak
 Аватар для kazak
3029 / 2350 / 155
Регистрация: 11.03.2009
Сообщений: 5,401
10.06.2010, 11:42     memcpy/CopyMemory + 2-мерный динамический массив #6
Цитата Сообщение от _lacrimosa_ Посмотреть сообщение
Значит calloc-ом можно сразу построить 2-мерный динамический массив в непрерывном участке памяти
Непрерывно можно выделить память только для одномерного массива, но с ним можно работать как с двумерным - a[i][j] => a[i*columnSize + j]
Lord_Voodoo
Супер-модератор
 Аватар для Lord_Voodoo
8501 / 2168 / 61
Регистрация: 07.03.2007
Сообщений: 10,836
Завершенные тесты: 1
10.06.2010, 11:47     memcpy/CopyMemory + 2-мерный динамический массив #7
_lacrimosa_, нет, но вы же все равно для каждой строки выделяете динамически память, поэтому можно без проблем сразу выделять и инициализировать
_lacrimosa_
1 / 1 / 0
Регистрация: 10.06.2010
Сообщений: 26
10.06.2010, 12:05  [ТС]     memcpy/CopyMemory + 2-мерный динамический массив #8
В общем я понял. В моём коде двумерный массив представлен так: есть одномерный непрерывный массив из адресов. Каждый элемент этого массива это адрес одномерного массива float'ов. Таким образом, сами данные (5*5 float'ов) могут быть в разных участках памяти (однако непрерывно хранятся только строки по 5 float'ов).

Ключевым моментом в использовании memcpy было непрерывность памяти из этих 25 эл-тов. Поэтому компилятор и ругался, что есть только 20 байт (5 эл-тов).

В статическом 2-мерном память действительно непрерывно выделяется. В Delphi видимо также, функцией setlength().
Dulotanka
Сообщений: n/a
03.09.2010, 10:49     memcpy/CopyMemory + 2-мерный динамический массив #9
нужно 2-мерный массив создавать так:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
float** Create(int x, int y)
{
    float **p = new BYTE[sizeof( float* ) * y + x * y * sizeof( float )]; //захватываем память под y указателей и x*y элементов
    if ( !p ) return p;
    p[0] = (float *)(p + y);                            //ставим 0 указатель на 0 строку массива
    for( int i = 1; i < y ; i++)
        p[i] = (float*)((BYTE*)p[i - 1] + sizeof( float ) * x * y);
    return p;
}
    //так создаются массивы
    float **p1 = Create( 5, 5 );
    float **p2 = Create( 5, 5 );
    //так пользуемся элементами массива
    for( int x = 0; x < 5 ; x++)
        for ( int y = 0; y < 5; y++)
             p1[x][y] = x + y * 5;
 
   //или так, результат эквивалентен
   for( int i = 0 ; i < 5 * 5 ; i++)
       p1[0][i] = i;                            //элементы расположны по порядку после (0;4) идет (1;0)
  //так копируем
   CopyMemory( p2[0] , p1[0] , 5 * 5 * sizeof( float ) );  //p1 - указывает на 0 указатель 0 строки, p1[0] - это указатель на 0 строку массива
за работу кода не отвечаю, но логика должна быть ясна
easybudda
Модератор
Эксперт С++
 Аватар для easybudda
9373 / 5423 / 914
Регистрация: 25.07.2009
Сообщений: 10,423
03.09.2010, 11:13     memcpy/CopyMemory + 2-мерный динамический массив #10
Цитата Сообщение от _lacrimosa_ Посмотреть сообщение
В общем я понял. В моём коде двумерный массив представлен так: есть одномерный непрерывный массив из адресов. Каждый элемент этого массива это адрес одномерного массива float'ов. Таким образом, сами данные (5*5 float'ов) могут быть в разных участках памяти (однако непрерывно хранятся только строки по 5 float'ов).
Ключевым моментом в использовании memcpy было непрерывность памяти из этих 25 эл-тов. Поэтому компилятор и ругался, что есть только 20 байт (5 эл-тов).
Правильно поняли! Если так необходимо иметь массив из 25 последовательно идущих элементов, при этом работать с ним, как с двухмерным массивом, можно как-то так поступить:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <iomanip>
 
int main(){
    int size = 30;
    int row = 5, column = 6;
    int * arr = new int [ size ];
    
    for ( int i = 0; i < size; ++i )
        arr[i] = i + 1;
    
    for ( int i = 0; i < row; ++i ){
        for ( int j = 0; j < column; ++j )
            std::cout << std::setw(2) << std::right << std::setfill('0') << arr[ i * column + j ] << ' ';
        std::cout << std::endl;
    }
    
    delete [] arr;
    return 0;
}
Цитата Сообщение от Dulotanka Посмотреть сообщение
за работу кода не отвечаю, но логика должна быть ясна
Не-а! Объясните как-нибудь доходчиво...
Dulotanka
Сообщений: n/a
22.09.2010, 12:18     memcpy/CopyMemory + 2-мерный динамический массив #11
По поводу 1 варианта рисовать надо, там в float **p сначала идут указатели (float*) в количестве y штук, затем сами данные (float) в количестве x*y. Нулевой указалеть (float* p[0]), указывает на нулевую строку массива, т.е. чтоб получить элемент 0;0 *(p[0] + 0) или p[0][0]. Первый укачатель, указывает на первую строку. В общем чтоб понятней было надо рисовать).. чето не хочется мне.

Вот второй вариант попроще, тут одномерный массив представляется двумерным
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
template <class T>
class CArray2{
    T *m_pData;
    WORD m_wSizeCol;    
public:
    CArray2(){m_pData = 0;}
    ~CArray2(){if(m_pData) delete m_pData;}
    void Destroy(){if(m_pData) delete m_pData;}
    void Create(WORD wSizeCol, WORD wSizeRow)
    {
        Destroy();
        m_pData = new T[wSizeCol * wSizeRow];
        m_wSizeCol = wSizeCol;      
    }
    T* operator[](int i){return m_pData+i*m_wSizeCol;}
};
 
CArray2<float> arrFloat;
arrFloat.Create(5, 5);     //создаем массив размерностью 5х5
arrFloat[1][2] = 4.5;      //заносим значение
 
//а вот тоже самое, что в сообщение над этим. Только с использованием моего класса
 
int size = 30;
int row = 5, column = 6;
CArray2<int> arr;
arr.Create( row, column );
        
for ( int i = 0; i < size; ++i )
    arr[0][i] = i + 1;
        
for ( int i = 0; i < row; ++i ){
     for ( int j = 0; j < column; ++j )
           std::cout << std::setw(2) << std::right << std::setfill('0') << arr[ i ][ j ] << ' ';
     std::cout << std::endl;
}
Этот вариант 100% рабочит, в консольке проверил)
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
22.09.2010, 14:27     memcpy/CopyMemory + 2-мерный динамический массив
Еще ссылки по теме:

C++ Пяти мерный динамический массив
C++ 5-ти мерный массив
Memcpy, buffer overflow. Может ли возникнуть ошибка в функции memcpy C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
accept
4838 / 3237 / 165
Регистрация: 10.12.2008
Сообщений: 10,682
22.09.2010, 14:27     memcpy/CopyMemory + 2-мерный динамический массив #12
C++
1
2
3
    int K = NUM * sizeof(float);
    for (int i = 0; i < NUM; i++)
        memcpy(C[i], D[i], K);
Yandex
Объявления
22.09.2010, 14:27     memcpy/CopyMemory + 2-мерный динамический массив
Ответ Создать тему
Опции темы

Текущее время: 17:49. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru