Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Надежно ли обнулять массив с помощью memset()? 
:(
    Опции темы
Royan
Дата 25.2.2006, 07:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Dreamer
***


Профиль
Группа: Участник Клуба
Сообщений: 1708
Регистрация: 14.9.2002
Где: Лондон

Репутация: нет
Всего: 15



Допустим есть такой код

Код

double **mx = new double*[col - 1];
        for(int i = 0; i < col - 1; i++) {
            mx[i] = new double[row];
            sizeOfMx += sizeof(double) * row;
        } 

memset(mx, 0, sizeOfMx);



Надежно ли обнулять память массива таким образом? Могут ли быть какие-то побочные эффекты. Меня интересуют 32 и 64 битные платформы, используя g++, gcc, icl, cl(msvc). Насколько я знаю на cl особых проблем нет, но все-таки хочется знать точку зрения профессионала


--------------------
Открыта вакансия Junior Java Developer'а в нашем лондонском офисе, подробнее можно узнать здесь
PM MAIL MSN   Вверх
Daevaorn
Дата 25.2.2006, 10:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2155
Регистрация: 29.11.2004
Где: Москва

Репутация: 51
Всего: 70



Royan,
нет таким образом нельзя вообще! Получишь утечку памяти. У тебя же двухмерный массив! Вот если бы это был обычный массив POD типа, то использование memset вполне легально и надежно. Но в твоём случае это преступление. Откуда ты решил что так можно писать?

Это сообщение отредактировал(а) Daevaorn - 25.2.2006, 10:56
PM MAIL WWW   Вверх
MAKCim
Дата 25.2.2006, 15:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 52
Всего: 207



если тебе надо занулить все строки матрицы пиши
Код

double** mx=new double* [col-1];
for (int i=0; i<col-1; i++) mx[i]=new double [row]();
...



--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
Royan
Дата 25.2.2006, 17:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Dreamer
***


Профиль
Группа: Участник Клуба
Сообщений: 1708
Регистрация: 14.9.2002
Где: Лондон

Репутация: нет
Всего: 15



MAKCim, Так не могу очень долго. Массив используется в части, где время критично, поэтому необходимо его очень быстро обнулять к тому же твоим способом я тоже получу утечку, а чтобы этого не случилось, придется еще его и удалять.

Daevaorn, Мне казалось, что в любом массиве элементы располагаются друг за другом. А можешь объяснить, в чем отличие динамического массива от статического с физической точки зрения, откуда там возникает утечка?


--------------------
Открыта вакансия Junior Java Developer'а в нашем лондонском офисе, подробнее можно узнать здесь
PM MAIL MSN   Вверх
MAKCim
Дата 25.2.2006, 18:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 52
Всего: 207



Цитата

MAKCim, Так не могу очень долго. Массив используется в части, где время критично, поэтому необходимо его очень быстро обнулять

что значит долго? Обнуляется каждая строка в процессе создания
Цитата

к тому же твоим способом я тоже получу утечку, а чтобы этого не случилось, придется еще его и удалять.

А в твоем примере нет утечки? Сделай класс, в деструкторе удаление...
Цитата

А можешь объяснить, в чем отличие динамического массива от статического с физической точки зрения, откуда там возникает утечка?

в статическом не может быть утечки, т. к размещается в стеке (память автоматически освобождается), память для дин. массива выделяется в куче (ответственность за удаление на пользователе)


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
Fin
Дата 25.2.2006, 18:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дракон->Спать();
**


Профиль
Группа: Участник
Сообщений: 687
Регистрация: 4.1.2006

Репутация: 3
Всего: 10



Цитата(Royan @ 25.2.2006, 16:56 Найти цитируемый пост)
Daevaorn, Мне казалось, что в любом массиве элементы располагаются друг за другом. А можешь объяснить, в чем отличие динамического массива от статического с физической точки зрения, откуда там возникает утечка?

В двухмерном массиве, созданом не динамически, члены массива идут один за другим. Пример:
Код

  char ch[2][2]={"c","a"};

Вот вырезка, как этот массив разместился у меня в памяти:
Цитата

0012FF7C  63 00 61 00

Теперь расмотрим динамический массив. В первую размерность записываются не данные, а адреса на вторую размерность. Во второй размерности уже записываются сами данные.
Пример:
Код

    char **ch=new char *[2];
    for (int i=0; i<2; i++) ch[i]=new char[2];
    ch[0][0]='c';
    ch[0][1]=0;
    ch[1][0]='a';
    ch[1][1]=0;

После выполнения в самой переменной ch был записан адрес на выделенную память.
Цитата

00322908  50 29 32 00 98 29 32 00

Это так выгледела первая размерность.
Так выгледит вторая размерность
Цитата

00322950  63 00
00322998  61 00

Если ты даеш memset для двухмерного динамического массива в твоем случае, то ты просто напросто затираеш ссылки на вторую размерность. И последуюшие попытки обрашения ко второй размерности должны привести к вылету программы.
Добавлено @ 18:48
Если ты хочеш обнулять вторую размерность, нужно делать
Код

for(int i = 0; i < col - 1; i++) {
            memset(mx[i],0, sizeof(double)*row);
}


Это сообщение отредактировал(а) Fin - 25.2.2006, 18:42


--------------------
Пролетал мимо.
PM MAIL   Вверх
Royan
Дата 25.2.2006, 19:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Dreamer
***


Профиль
Группа: Участник Клуба
Сообщений: 1708
Регистрация: 14.9.2002
Где: Лондон

Репутация: нет
Всего: 15



MAKCim, Дело в том, что создание/удаление элементов априорно медленнее, чем простая запись нулей. Хотя бы, поэтому для меня предложенный тобой вариант не годится. Статический массив мне не подойдет, у меня там алгоритм работы на динамике построен.


Fin, +1 Теперь все кристально ясно. Честное слово я бы проставился за такой ответ ;) Это надо пометить в F.A.Q!

Но вопрос о наиболее оптимальном способе обнуления я бы закрывать не хотел. Несомненно, вариант, предложенный Fin, значительно лучше, чем просто присвоение каждому элементу массива нуля, но может кто-то знает еще более изящный способ?



--------------------
Открыта вакансия Junior Java Developer'а в нашем лондонском офисе, подробнее можно узнать здесь
PM MAIL MSN   Вверх
Daevaorn
Дата 25.2.2006, 19:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2155
Регистрация: 29.11.2004
Где: Москва

Репутация: 51
Всего: 70



Цитата(Royan @ 25.2.2006, 20:16 Найти цитируемый пост)
Но вопрос о наиболее оптимальном способе обнуления я бы закрывать не хотел. Несомненно, вариант, предложенный Fin, значительно лучше, чем просто присвоение каждому элементу массива нуля, но может кто-то знает еще более изящный способ?

Изящнее не существует. Добавление "()" к твоему коду - это предел изящности
PM MAIL WWW   Вверх
maxim1000
Дата 25.2.2006, 20:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: 17
Всего: 110



можно сделать одномерный массив A размером M*N
и к нему еще сделать доп. массив указателей на начала строк B[i]=A+RowLength*i
тогда и создавать, и удалять нужно будет с помощью одного new и одного delete
а это, как мне кажется, и будут основные затраты при создании/удалении
а для обнуления можно будет использовать тот факт, что все элементы идут друг за другом и вызывать memset для A...


--------------------
qqq
PM WWW   Вверх
MAKCim
Дата 25.2.2006, 20:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 52
Всего: 207



Цитата

Дело в том, что создание/удаление элементов априорно медленнее, чем простая запись нулей

и у тебя и у меня идет создание double-ов
Код

ms[i]=new double[row];

выражение
Код

ms[i]=new double[row]();

обнуляет каждый double
чем эта запись медленнее memset, и каким образом устроен memset в таком случае
получается, что
Код

int* p=new int(0);

медленнее чем
Код

int* p=new int;
memset(p,0,sizeof(int))




--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
Royan
Дата 25.2.2006, 22:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Dreamer
***


Профиль
Группа: Участник Клуба
Сообщений: 1708
Регистрация: 14.9.2002
Где: Лондон

Репутация: нет
Всего: 15



MAKCim, У меня создание массива только в оном месте, далее могут произойти десятки тысяч обнулений. Просто в примере эти опреации я написал друг за другом.


--------------------
Открыта вакансия Junior Java Developer'а в нашем лондонском офисе, подробнее можно узнать здесь
PM MAIL MSN   Вверх
ДобренькийПапаша
Дата 25.2.2006, 22:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1278
Регистрация: 14.1.2006
Где: г.Москва

Репутация: нет
Всего: 7



for(i=0; i<n; i++)
{
for(j=0;j<n;j++)
a[i][j]=0;
}

А что, так нельзя?


--------------------
Меня зовут Себастьян Парейра, торговец чёрным деревом.
PM MAIL   Вверх
YonasBriginas
Дата 26.2.2006, 01:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 15
Регистрация: 25.2.2006

Репутация: нет
Всего: нет



можно только цикл ускорить, а с памятью самое оптимальное решение было предложено.
Код

int k = sizeof(double)*row;
// префиксная операция инкремента выполняется без создания временой 
// переменной в отличии от постфиксной операции, которая в свою очередь использует префиксную
for(int i = 0; i < col - 1; ++i)    
{
    memset(mx[i],0, k);
}

PM MAIL   Вверх
Royan
Дата 26.2.2006, 05:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Dreamer
***


Профиль
Группа: Участник Клуба
Сообщений: 1708
Регистрация: 14.9.2002
Где: Лондон

Репутация: нет
Всего: 15



maxim1000, Только сейчас понял твою мысль smile ты вот это имел ввиду?
Код

template < typename _Ty >
_Ty **AllocateMatrix( int nRows, int nCols) {
        _Ty **ppi = new _Ty*[nRows];        
        _Ty *curPtr = new _Ty [nRows * nCols]();
        for(int i = 0; i < nRows; i++) {
                *(ppi + i) = curPtr;
                curPtr += nCols;
        }
        return ppi;
}

template < typename _Ty >
void FreeMatrix(_Ty** mx) {
        delete [] *mx;
        delete [] mx;
}


2YonasBriginas, Спасибо за внимательность smile, правда, насколько мне известно, постфиксные операции на базовых типах оптимизируются компилятором (во всяком случае, это одна из первых вещей, которую может и оптимизирует любой достойный компилятор)


--------------------
Открыта вакансия Junior Java Developer'а в нашем лондонском офисе, подробнее можно узнать здесь
PM MAIL MSN   Вверх
MAKCim
Дата 26.2.2006, 10:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 52
Всего: 207



Цитата

У меня создание массива только в оном месте, далее могут произойти десятки тысяч обнулений. Просто в примере эти опреации я написал друг за другом.

тогда ладно, хотя memset тоже скорее всего на циклах основана
я думаю что-то типа
Код

void memset(void* ptr,char zn, unsigned int size) 
{
    char* pointer=static_cast<char*>(ptr);
    while (size--) *pointer--=zn;
}



--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0906 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.