Мастера DELPHI, Delphi programming community Рейтинг@Mail.ru Титульная страница Поиск, карта сайта Написать письмо 
| Новости |
Новости сайта
Поиск |
Поиск по лучшим сайтам о Delphi
FAQ |
Огромная база часто задаваемых вопросов и, конечно же, ответы к ним ;)
Статьи |
Подборка статей на самые разные темы. Все о DELPHI
Книги |
Новинки книжного рынка
Новости VCL
Обзор свежих компонент со всего мира, по-русски!
|
| Форумы
Здесь вы можете задать свой вопрос и наверняка получите ответ
| ЧАТ |
Место для общения :)
Орешник |
Коллекция курьезных вопросов из форумов
KOL и MCK |
KOL и MCK - Компактные программы на Delphi
Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / rsdn.org

 
Чтобы не потерять эту дискуссию, сделайте закладку « предыдущая ветвь | форум | следующая ветвь »
Страницы: 1 2

Что выдаст функция


Sha ©   (02.06.17 14:30[20]

> Тимохов Дима ©   (02.06.17 14:15) [19]

интересно другое, FillChar зачем?


Тимохов Дима ©   (02.06.17 14:37[21]


> Sha ©   (02.06.17 14:30) [20]
> > Тимохов Дима ©   (02.06.17 14:15) [19]
> интересно другое, FillChar зачем?


// Дабы не оставить возможные новые члены
// не инициализированными инициализируем нулям.


ибо // Потенциально могут добавляться члены.


Sha ©   (02.06.17 14:41[22]

> Тимохов Дима ©   (02.06.17 14:37) [21]

так лучше не делать,
ибо потенциально это может привести к затиранию нулем указателя на строку
и, как следствие, к утечке памяти


Тимохов Дима ©   (02.06.17 14:48[23]


> Sha ©   (02.06.17 14:41) [22]
> > Тимохов Дима ©   (02.06.17 14:37) [21]
> так лучше не делать,
> ибо потенциально это может привести к затиранию нулем указателя
> на строку и, как следствие, к утечке памяти

Конечно, ты прав.

Вопрос, в другом, что код то в общем-то невинный.
Зачастую что-то похожее может прийти еще из старого кода, а строка была добавлена позднее. И вот тебе и утечка.
К тому же Button1 приводит к ошибке, Button2 - нет. Опять же, понятно почему.

Я к тому, что может быть полезно для новичков знать такую особенность.

Если уж очень мне надо сохранить функционал FillChar (т.е. умолчательную инициализацию), но не получить мемлик, то пишу обычно так:

function InitPerson(const FIO: String; Age: Integer): TPerson;
var
  R: TPerson;
begin
 // Дабы не оставить возможные новые члены
 // не инициализированными инициализируем нулям.
 FillChar(R, SizeOf(R), 0);
 R.FIO := FIO;
 R.Age := Age;
 Result := R;
end;


Sha ©   (02.06.17 16:12[24]

> Тимохов Дима ©   (02.06.17 14:48) [23]
> Если уж очень мне надо сохранить функционал FillChar

а тут тоже FillChar не нужен,
т.к. благодаря магии компилятора R будет проинициализирована


Тимохов Дима ©   (02.06.17 16:23[25]


> Sha ©   (02.06.17 16:12) [24]
> > Тимохов Дима ©   (02.06.17 14:48) [23]
> > Если уж очень мне надо сохранить функционал FillChar
>
> а тут тоже FillChar не нужен,
> т.к. благодаря магии компилятора R будет проинициализирована

и даже Integer? )))


Sha ©   (02.06.17 16:29[26]

а нафига его инициализировать, если это никогда не приведет к ошибке?


Тимохов Дима ©   (02.06.17 16:45[27]


> Sha ©   (02.06.17 16:29) [26]
> а нафига его инициализировать, если это никогда не приведет
> к ошибке?

Предпочитаю не оставлять неинициализированные переменные.


Игорь Шевченко ©   (03.06.17 10:35[28]

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

В свое время бывший коллега (ныне покойный) писал такой код:

A := 0;
A := FieldByName('B').AsInteger;

Когда его спросили, зачем первое присваивание, ответ был: "А вдруг поле не найдется"


Тимохов Дима ©   (03.06.17 12:57[29]


> Игорь Шевченко ©   (03.06.17 10:35) [28]
> FillChar не нужен более чем совсем, во-первых, он не делает
> ничего полезного, во-вторых затрудняет понимание кода.


Иногда - нужен, иногда - не нужен. Зависит от ситуации.

В VCL пример есть. Вот, например DBTables.pas -> TDatabase.Execute, или StdCtrls.pas -> TCustomListBox.ItemRect.
Факт - есть примеры использования FillChar для очистки результата типа record.

Еще раз: FillChar(Result,...) - это способ дать умолчательное значение для результата типа Record. Но этот способ таит в себе тонкости, которые надо знать начинающим программистам, которые еще не сталкивались с подобными тонкостями. Собственно, я для этого и написал свой комментарий выше.


Pavia ©   (03.06.17 21:20[30]

Вообще-то FillChar как раз и нужен
Если его не сделать то в первом коде в первом рекорде будет инвалидный указатель.


Pavia ©   (03.06.17 21:26[31]


> Когда его спросили, зачем первое присваивание, ответ был:
>  "А вдруг поле не найдется"

Это просто скорее всего человек джавист.

Кстати навеяло ещё вопрос.
Нужно ли тут оставить OutInt:=0; ? Или обнулять должен Slot принимающий эмитированный сигнал?


procedure ReadInt(var OutInt:Integer);
var str:String;
begin
repeat
Read(str);
until (IsNumber(str) or IsEndOfRead or IsTermitateChar(Ch) or IsFullString(OutStr));  
if IsNumber(str) then
  OutInt:=StrToInt(Str)
  else
    begin
    OutInt:=0;
    emitFirstSignal(@ReadInt, @OutInt, nil);
    end;
end;


Тимохов Дима ©   (03.06.17 21:56[32]


> Нужно ли тут оставить OutInt:=0; ? Или обнулять должен Slot
> принимающий эмитированный сигнал?

Это как по контракту. Т.е. по спецификации слота.


Pavia ©   (03.06.17 22:39[33]


> Это как по контракту. Т.е. по спецификации слота.

О точно. У эмитора есть контракт. Спасибо, переписал так.

    Goal:=0;
    emitFirstSignal(@ReadInt, @OutInt, @Goal);
    OutInt:=Goal;


Игорь Шевченко ©   (03.06.17 22:39[34]

Тимохов Дима ©   (03.06.17 12:57) [29]


> Иногда - нужен, иногда - не нужен. Зависит от ситуации.
>
>
> В VCL пример есть. Вот, например DBTables.pas -> TDatabase.
> Execute, или StdCtrls.pas -> TCustomListBox.ItemRect.
> Факт - есть примеры использования FillChar для очистки результата
> типа record.


2006:

function TCustomListBox.ItemRect(Index: Integer): TRect;
var
 Count: Integer;
begin
 Count := Items.Count;
 if (Index = 0) or (Index < Count) then
   Perform(LB_GETITEMRECT, Index, Longint(@Result))
 else if Index = Count then
 begin
   Perform(LB_GETITEMRECT, Index - 1, Longint(@Result));
   OffsetRect(Result, 0, Result.Bottom - Result.Top);
 end else FillChar(Result, SizeOf(Result), 0);
end;


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

Keep it simple, Syndey!

Вот в XE5 написали гораздо понятнее:

function TCustomListBox.ItemRect(Index: Integer): TRect;
var
 Count: Integer;
begin
 Count := Items.Count;
 if (Index = 0) or (Index < Count) then
   Result := GetItemRect(Index)
 else if Index = Count then
 begin
   Result := GetItemRect(Index - 1);
   OffsetRect(Result, 0, Result.Bottom - Result.Top);
 end
 else
   Result := TRect.Empty;
end;


Игорь Шевченко ©   (03.06.17 22:40[35]


> procedure ReadInt(var OutInt:Integer);


Дальше пост можно не читать. Калверта зубрить наизусть!


Pavia ©   (03.06.17 22:49[36]


> Калверта зубрить наизусть!

У меня нет его книг. Не могли бы уточнить какую именно книгу вы имеете в виду?


Pavia ©   (03.06.17 23:16[37]


> Игорь Шевченко ©   (03.06.17 22:40) [35]

и вообще не надо принимать всё так близко к сердцу. На самом деле это черновик. OutInt элементарно заменяется на value просто это я себе напоминалку оставил. Теперь когда разобрался что есть var и какой контракт у эммитора можно смело заменить на value.


Игорь Шевченко ©   (04.06.17 10:44[38]

Pavia ©   (03.06.17 22:49) [36]

https://edn.embarcadero.com/article/10280


Страницы: 1 2 версия для печати

Написать ответ

Ваше имя (регистрация  E-mail 







Разрешается использование тегов форматирования текста:
<b>жирный</b> <i>наклонный</i> <u>подчеркнутый</u>,
а для выделения текста программ, используйте <code> ... </code>
и не забывайте закрывать теги! </b></i></u></code> :)


Наверх

  Рейтинг@Mail.ru     Титульная страница Поиск, карта сайта Написать письмо