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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Realloc в С++, чем плохо  
V
    Опции темы
feodorv
Дата 7.3.2012, 17:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

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



Бог ты мой, да в C те же проблемы. Если, скажем, внутри одной структуры определяются указатели на какие-то значения этой структуры, то беды при realloc не избежать:
Код

struct fullname
{
  char name[MAX_PATH];
  char *fileName;
};

struct fullname *list = NULL;
unsigned int listSize = 0;

BOOL addFile( const char *fullName )
{
  struct fullname *newlist, *current;

  if( listSize == 0 )
    newlist = (struct fullname *) malloc( sizeof(struct fullname) );
  else
    newlist = (struct fullname *) realloc( list, (listSize+1)*sizeof(struct fullname) );
  if( newlist == NULL ) return FALSE;

  list = newlist;
  current = &list[listSize++];

  strncpy( current->name, fullName, sizeof(current->name));
  current->name[sizeof(current->name)-1] = '\0';
  if( (current->fileName = strrchr( current->name, '/')) == NULL ) current->fileName = current->name;

  return TRUE;
}


И ещё пример. Здесь просто запомнили указатель на какой-то элемент списка, а потом сделали realloc:

Код

...
mySupperFile = &list[index];
...
addFile( newFile );
...
printf( "name = %s\n", mySupperFile->name);


Примеры выдуманы, но они демонстрирует опасный код, связанный с realloc. Такие ситуации лечатся тем, что нужно хранить не указатели, а смещения. Но от ошибок никто не застрахован...


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
sergioK1
Дата 7.3.2012, 17:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(xvr @ 7.3.2012,  16:10)
Цитата(sergioK1 @  7.3.2012,  17:00 Найти цитируемый пост)
И чем скомилированный код с ним отличаеться от того что без ?

Отличаться может координально. Вплоть до того, что memcpy работать для данного класса не будет, а operator =() будет.
Например:
Код

class String {
 char buffer[1024];
 char* last_ptr; // Where 'buffer' ends
public:
 String()
  {
   last_ptr=buffer;
  }

 void append(const char* str)
  {
   strcpy(last_ptr,str);
   last_ptr+=strlen(past_ptr);
  }

 void operator=(const String& s)
  {
   memcpy(buffer,s.buffer,sizeof(buffer));
   last_ptr=buffer+(s.last_ptr-s.buffer);
  }
};

Без operator=() этот класс после копирования начнет дописывать строки к оригиналу (откуда копировали), а не к себе.

что измениться есть вместо operator = будет метод Сlone ?
а  operator = будет private , для верности , а на С = просто не вызывать, 
да писать так не очень удобно , но компайлеру то какая разница ,?

Код

   void Clone(const String& s)
  {
   memcpy(buffer,s.buffer,sizeof(buffer));
   last_ptr=buffer+(s.last_ptr-s.buffer);
  }
};


Это сообщение отредактировал(а) sergioK1 - 7.3.2012, 17:49
PM MAIL   Вверх
bsa
Дата 7.3.2012, 17:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(feodorv @  7.3.2012,  18:35 Найти цитируемый пост)
Бог ты мой, да в C те же проблемы. 

C отличается от С++ тем, что на тебе лежит больше обязанностей по контролю правильности.
Цитата(sergioK1 @  7.3.2012,  18:40 Найти цитируемый пост)
что измениться есть вместо operator = будет метод Сlone ?

Изменится то, что стандартные методы работать с таким классом не будут. Зачем усложнять себе жизнь?
PM   Вверх
sergioK1
Дата 7.3.2012, 21:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(feodorv @ 7.3.2012,  16:35)
Такие ситуации лечатся тем, что нужно хранить не указатели, а смещения. Но от ошибок никто не застрахован...

Или писать свой  wrapper realloc он же Clone и копировать указатели/ссылки , или не копировать , в зависимости от задачи, 
в С++ это копи конструктор ,  но это  не значит что realloc это плохо,  

в случае с vector возникают  теже самые проблемы , 


feodorv - спасибо прояснил ситуацию , 
Вопрос решен 




Это сообщение отредактировал(а) sergioK1 - 8.3.2012, 00:14
PM MAIL   Вверх
xvr
Дата 8.3.2012, 09:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

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



Цитата(sergioK1 @  7.3.2012,  17:40 Найти цитируемый пост)
а  operator = будет private , для верности , а на С = просто не вызывать, 
да писать так не очень удобно , но компайлеру то какая разница ,?

Разница в том, что operator= будет вызываться автоматически компилятором (там, где надо), а Clone вам придется звать вручную. При этом запросто можно забыть и не позвать этот самый Clone (человеку свойственно ошибаться). А вот компилятор не ошибается. Ну и в конце концов у вас может и не быть возможности этот самый Clone позвать (как уже упоминал bsa, например при использовании stl контейнеров)

PS. В 99% реализации realloc внутри сделает free и malloc если его попросят увеличить выделенный блок, так что его использование не дает никаких преимуществ


PM MAIL   Вверх
sergioK1
Дата 8.3.2012, 10:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(xvr @ 8.3.2012,  08:37)
PS. В 99% реализации realloc внутри сделает free и malloc если его попросят увеличить выделенный блок, так что его использование не дает никаких преимуществ


На чем это утверждение основано ?  
мне как в суде аргуметы нужны и факты  smile , 

Это сообщение отредактировал(а) sergioK1 - 8.3.2012, 10:42
PM MAIL   Вверх
Alexeis
Дата 8.3.2012, 11:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

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



Цитата(sergioK1 @  8.3.2012,  11:20 Найти цитируемый пост)
На чем это утверждение основано ? 

Потому же менеджер кучи не резервирует дополнительного места после блока выделенной памяти. Расширение будет только если освободили память строго за текущим блоком при этом освобожденный блок был больше чем нужно для роста. Такое событие маловероятно. Если хотите реально иметь возможность выделять память с возможностью роста, то такое поведение можно сделать средствами ОС, в частности в Windows можно зарезервировать адресное пространство, но выделить только столько сколько нужно, а при необходимости до выделить память по зарезервированным адресам. Тогда получиться непрерывный кусок расширяемый кусок. 


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
sergioK1
Дата 8.3.2012, 11:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(Alexeis @ 8.3.2012,  10:03)
Цитата(sergioK1 @  8.3.2012,  11:20 Найти цитируемый пост)
На чем это утверждение основано ? 

Потому же менеджер кучи не резервирует дополнительного места после блока выделенной памяти. Расширение будет только если освободили память строго за текущим блоком при этом освобожденный блок был больше чем нужно для роста. Такое событие маловероятно. Если хотите реально иметь возможность выделять память с возможностью роста, то такое поведение можно сделать средствами ОС, в частности в Windows можно зарезервировать адресное пространство, но выделить только столько сколько нужно, а при необходимости до выделить память по зарезервированным адресам. Тогда получиться непрерывный кусок расширяемый кусок.

Это понятно ,но Я не уверен что он вызывает имеено malloc , если бы так то realloc был бы не нужен ,
а не другие механизмы , более низнего уровня,  
PM MAIL   Вверх
bsa
Дата 8.3.2012, 14:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(sergioK1 @  8.3.2012,  12:36 Найти цитируемый пост)
Это понятно ,но Я не уверен что он вызывает имеено malloc , если бы так то realloc был бы не нужен ,
а не другие механизмы , более низнего уровня,   

malloc/realloc/calloc/free работают с "кучей" (new/delete тоже, кстати), которая реализуется средствами стандартной библиотеки. К API системы это не имеет отношения (точнее, API используется только для изменения размеров собственно кучи). А куча - это как файловая система на диске, только без возможности фрагментации. Увеличить конкретный блок можно только:
или если после него есть свободное место
или если он находится в конце кучи, а другого подходящего куска в куче нет, в этом случае куча будет увеличена и блок будет увеличен соответственно.

Это сообщение отредактировал(а) bsa - 8.3.2012, 14:29
PM   Вверх
xvr
Дата 9.3.2012, 10:06 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

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



Цитата(sergioK1 @  8.3.2012,  10:20 Найти цитируемый пост)
На чем это утверждение основано ?  

На изучении некоторого количества сорцов RTL и на здравом смысле. Если вы хотите, что бы realloc мог сделать что то помимо free/malloc вам надо самому следить за тем, что и в какой последовательности вы просите расположить на куче. realloc не может перераспределить уже выделенную память, поэтому, если после куска, который вы хотите увеличить, что то уже лежит, то никаких вариантов кроме free/malloc уже не остается

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


Опытный
**


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

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



Цитата(xvr @ 9.3.2012,  09:06)
Если вы хотите, что бы realloc мог сделать что то помимо free/malloc вам надо самому следить за тем, что и в какой последовательности вы просите расположить на куче. realloc не может перераспределить уже выделенную память, поэтому, если после куска, который вы хотите увеличить, что то уже лежит, то никаких вариантов кроме free/malloc уже не остается

Не понял, если  если после куска, который вы хотите увеличить, что то уже лежит, то логике ,realloc сам вызовет malloc + memcpy,
или какой то свой механизм/алгоритм, 
Я ж не знаю лежит что-то после куска или нет , счас может лежать через 5 минут нет , 

про самому следить за тем, что и в какой последовательности вы просите расположить на куче это как ? 

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


Эксперт
****


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

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



Цитата(sergioK1 @  10.3.2012,  18:53 Найти цитируемый пост)
Не понял, если  если после куска, который вы хотите увеличить, что то уже лежит, то логике ,realloc сам вызовет malloc + memcpy,
или какой то свой механизм/алгоритм,
Ты все понял. После malloc+memcpy+free будет выделен НОВЫЙ участок памяти, и старые указатели станут неверны.
Цитата(sergioK1 @  10.3.2012,  18:53 Найти цитируемый пост)
Я ж не знаю лежит что-то после куска или нет , счас может лежать через 5 минут нет
Вот именно.
Цитата(sergioK1 @  10.3.2012,  18:53 Найти цитируемый пост)
про самому следить за тем, что и в какой последовательности вы просите расположить на куче это как ? 
Написать свой собственный менеджер кучи.
PM   Вверх
sergioK1
Дата 12.3.2012, 00:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



он и в С не особо то и нужен, все равно нужно клонировать объект (хоть с =() , хоть и без ),
тут вопрос закрыт

еще момент , раз уж зашла речь за вектор , 

Код

 template<class T, class U = std::allocator<T> >
 class MyVector : public vector<T,U>{      
 }


стандартный вектор на два множит , мне надо 100 прибавлять,   правильно алокатор писать ?
должен быть свой класс наследник std::allocator? , какие методы перегружать ? или у вектора resize перегрузить ?



Это сообщение отредактировал(а) sergioK1 - 12.3.2012, 00:32
PM MAIL   Вверх
xvr
Дата 12.3.2012, 08:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

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



Цитата(sergioK1 @  12.3.2012,  00:01 Найти цитируемый пост)
стандартный вектор на два множит ,

Вектор имеет право изменять размер буфера как ему захочется, но снаружи это не видно. size() всегда будет возвращать размер реальных данных. А вот capacity() будет возвращать нечто большее.

Цитата(sergioK1 @  12.3.2012,  00:01 Найти цитируемый пост)
правильно алокатор писать ?

Это не поможет, вектор стартегию выделения памяти (с запасом) на allocator не отдает.


Цитата(sergioK1 @  12.3.2012,  00:01 Найти цитируемый пост)
 мне надо 100 прибавлять,

Управляйте размером и резервацией в векторе явно (resize() и reserve())

Цитата(sergioK1 @  12.3.2012,  00:01 Найти цитируемый пост)
какие методы перегружать ?

Никакие. У STL контейнеров нет виртуальных методов

PM MAIL   Вверх
mes
Дата 12.3.2012, 09:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Цитата(sergioK1 @  11.3.2012,  23:01 Найти цитируемый пост)
 мне надо 100 прибавлять

из простого, написать свой (внешний) push_back, который будет ресайзить по нужной стратегии... 





--------------------
PM MAIL WWW   Вверх
Страницы: (4) Все 1 [2] 3 4 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
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.2128 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


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

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