[cdev] Задача №4 (Кочев Владислав, Вахрушев Сергей)

Grigoriy A. Sitkarev sitkarev на komitex.ru
Ср Дек 7 20:21:18 MSK 2011


Всех приветствую.

07.12.2011 11:07, Кочев Владислав пишет:
> Здравствуйте, по поводу предыдущего замечания:
>   >"realloc(3) может не сработать и вернуть NULL, в таком случае вы
> затрёте рабочий указатель на выделенный блок памяти в структуре. "
> Память не затирается, т.к<цитата>: "Если  запрос  выполнить  не
>          удается  или  новый  размер  равен нулю, возвращается NULL.  Если вызов
>          realloc()  завершился  неудачно,  то  старый   блок   памяти   остается
>          нетронутым: он не освобождается и не перемещается"
> Честно говоря, я не вижу ошибок, все делали точь в точь как описано по ссылкам,
> которые вы дали.

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

  - Во-первых, потому что вы воспринимаете любое замечание как критику 
лично вас, а не вашего кода.

  - Во-вторых, потому что вы категорически не способны сами разбираться 
в своих же ошибках, даже в том случае если вам укажут что "это работать 
не будет".

  - В-третьих, вы не умеете читать, а точнее, извлекать информацию из 
текста. Может быть вы и прочитали всё что я просил, но выводов и анализа 
не сделали.

> В прошлый раз вы сказали, что
>
> "1. malloc(3) может не сработать и вернуть NULL. Нигде не проверяется что
> он возвращал.
>
> 2. realloc(3) может не сработать и вернуть NULL, в таком случае вы
> затрёте рабочий указатель на выделенный блок памяти в структуре.
>
> 3. Изменять размер блока памяти, где хранятся указатели, надо не каждый
> раз при добавлении, а сразу выделять блок большего размера а затем
> заполнять его, поддерживая счётчик занятых и выделенных мест для
> указателей. Если окажется, что места для добавления очередного указателя
> нет, тогда размер блока увеличивается в два раза, через realloc(3).
>
> 4. parray_free() должен освобождать все ресурсы, занимаемые массивом
> указателей. Кроме этого, его декларация не соответствует прототипу в
> заголовке, предложенного вам. Это важно. "
> Вы в  прошлый  раз сказали еще, что нужно отслеживать была ли выделена память,
> добавили тоже.

> Это все исправили ведь, что еще может быть не так?
> ps. Стиль еще будем смотреть.

Т.к. у вас в голове модель ментальная memory management не верно 
сложилась, вы полагаете что вы "всё исправили". На самом деле, вы, 
пытаясь исправить, наделали ещё больше ошибок. Я категорически не люблю 
тыкать конкретно в какое-то место, по той причине что вы опять же 
бездумно просто переправите на так как я напишу, а в следующий раз 
будете делать точно такие же ошибки, потому что в сути проблемы вы не 
разобрались.

realloc(3) не гарантирует что он выделит блок памяти запрошенного 
размера, но он также не гарантирует что при увеличении блока его 
начальный адрес останется прежним. Вы, утверждая что прочитали всё что я 
вам дал, этого не поняли и с семантикой realloc(3) не разобрались.

Вот вырезка из parray_add(). Скобки, кстати, безобразно расставлены. И 
никаких `;' после них не нужно, это не определения структур и не 
завершения выражений.

---------------------->8-------------------------------

/*
  * Здесь неверно определяется условие для увеличения
  * размера блока. Условие должно быть V->Count == V->SIZE.
  * Иначе говоря, "места больше нет тогда, когда хранится
  * указателей уже столько, сколько их было выделено".
  */

if (V->Count+1 == V->SIZE){
	void *p;

	/*
	 * Здесь realloc(3) в p может вернуть адрес
	 * не равный V->DATA. Содержимое старого блока
	 * будет перемещено в новый блок, это realloc(3)
	 * выполняет самостоятельно.
	 */

	p = realloc(V->DATA, V->SIZE*sizeof(void *)*2);
	if (p == NULL){
		fprintf(stderr, "can't realloc parray data\n");
		return -1;
	};

	/*
  	 * Новый адрес блока из p, который может не совпадать
	 * со старым адресом блока, никуда не сохраняется.
	 * Изменяется только поле размера блока.
	 */

	V->SIZE *= 2;
};

/*
  * Здесь уже может быть или:
  * - затёрто слово в другом блоке памяти, не относящиеся
  * к блоку, размер которого хотелось изменить, т.к.
  * его начальный адрес уже не находится в V->DATA;
  * - затёрто слово в другом блоке или служебных структурах
  * аллокатора, т.к. блок нужно было увеличить, но условие
  * увеличения блока в `if ()' ошибочно.
  */
V->DATA[V->Count] = p;

----------------------8<-------------------------------

Как и почему это нужно исправлять -- думайте сами. Причину, по которой я 
этого не делаю за вас, я уже объяснил.

--
Г.А.




Подробная информация о списке рассылки cdev