Конференция "Прочее" » Вопрос по уничтожению объектов
 
  • 123-ий © (09.02.09 07:42) [0]
    Тут как бы надо знать устройство дельфового менеджера памяти на более высоком уровне, чем его знаю я. Поэтому спрошу в сюда.
    вот код:

    function GetSomeList: TStringList;
    begin
     Result := TStringList.Create;
     // Заполняю стринглист
    end;


    далее я вызываю данную функцию, например

    SomeListBox.Items := GetSomeList;


    теперь результат работы функции GetSomeList надо как-то уничтожить.
    Если сделать
    GetSomeList.Free

    - функция выполняется два раза, а это не оптимально, да и порой неудобно. Каким образом лучше реализовать? То есть мне просто надо сделать функцию, возвращающую стринглист и чтобы без утечки памяти.
  • MBo © (09.02.09 07:50) [1]
    сделай процедуру, которой передаешь созданный TStringList, потом его уничтожаешь, когда нужно.
  • Palladin © (09.02.09 08:04) [2]
    Procedure FillStringList(p_theSL:TStringList);
    Begin
     .. заполняем
    End;

    Var
     theSL:TStringList;
    Begin
     theSL:=TStringList;
     Try
      FillStringList(theSL);
      ...
     Finally
      theSL.Free;
     End;
    End;



    это - правильно
  • Palladin © (09.02.09 08:06) [3]
    зачем создавать TStringList для св-ва TStrings если оно уже создано и используется в объекте

    Procedure FillStringList(p_theSL:TStrings);
    Begin
    .. заполняем
    End;

    FillStringList(SomeListBox.Items);
  • korneley © (09.02.09 08:13) [4]

    > Palladin ©   (09.02.09 08:04) [2]
    > theSL:=TStringList;

    theSL:=TStringList.Create;

    Я не смеюсь, мало ли, чего недопонял :)
  • Palladin © (09.02.09 08:13) [5]
    :) никто не застрахован от описек и недописек :)
  • Skyle © (09.02.09 08:22) [6]

    > korneley ©   (09.02.09 08:13) [4]

    Это не чистый дельфи, это Palladin Delphi Extension ®
  • 123-ий © (09.02.09 09:27) [7]

    > Palladin ©   (09.02.09 08:04) [2]

    идею понял. так и сделаю ибо проще. спасибо.
    а все таки интересно, как ведет себя менеджер памяти. Вот когда я делаю так:
    SomeListBox.Items := GetSomeList;
    в SomeListBox.Items передается указатель на стринглист созданный функцией GetSomeList. Если например сделать так:

    var
     TempList: TStringList;
    begin
     TempList := GetSomeList;
     try
       SomeListBox.Items := TempList;
     finally
       TempList.Free;
     end;
    end;


    если в TempList передается указатель на стринглист, созданный функцией GetSomeList, то при выполнении строки TempList.Free этот самый стринглист должен умереть. Я прав?
  • Сергей М. © (09.02.09 09:30) [8]

    > 123-ий ©   (09.02.09 09:27) [7]


    > Я прав?


    Угу.
  • Palladin © (09.02.09 09:41) [9]

    > 123-ий ©   (09.02.09 09:27) [7]

    Абсолютно, но функций создающих и возвращающих объект какого то класса, нужно по возможности избегать. Все дело в том, что в процессе создания и/или инициализации этого объекта может произойти исключение и, в следствии этого утечка памяти.

    Например

    Function CreateMyObj:TMyClass;
    Begin
     Result:=TMyClass.Create;
     Result.Prop1:=Value1; // предположим, здесь возникает исключение
    End;

    Var
    obj:TMyClass;
    Begin
     obj:=CreateMyObj;
     Try
      ...
     Finally
      obj.Free; // бесполезно, объект создан, но исключение произошло не в Try/Finally, а во время выполнения функции, соответственно после исключения при назначении свойству значения, ссылка на созданный объект теряется
     End;
    End;

  • KSergey © (09.02.09 09:42) [10]
    > Palladin ©   (09.02.09 08:04) [2]
    > Procedure FillStringList(p_theSL:TStringList);
    > Begin
    >  .. заполняем
    > End;

    Тогда даже лучше

    Procedure FillStringList(p_theSL:TStrings);



    Тогда туда можно будет передавать в том числе и Items от SomeListBox и не придется создавать временный, а потом из него копировать.
  • Palladin © (09.02.09 09:43) [11]
    Именно в [3], по этому поводу, я и исправился, более внимательней прочитав вопрос )
  • KSergey © (09.02.09 09:44) [12]
    > Palladin ©   (09.02.09 09:43) [11]

    а, точно, не заметил, сорри.
  • KSergey © (09.02.09 09:45) [13]
    А почему вопрос задан в потрепаться, а не в тематической?? вполне себе тематический вопрос, по-моему.
  • Anatoly Podgoretsky © (09.02.09 09:51) [14]
    > Palladin  (09.02.2009 9:41:09)  [9]

    Это можно легко исправить, немного переделав функцию, но смысла нет.
  • 123-ий © (09.02.09 10:03) [15]

    > KSergey ©   (09.02.09 09:45) [13]

    на всякий случай. туда предпочитаю не лазить почему то. :)

    > Anatoly Podgoretsky ©   (09.02.09 09:51) [14]

    смысла то нет, а все тки расскажите. =) интересно
  • test © (09.02.09 10:15) [16]
    KSergey ©   (09.02.09 09:45) [13]
    Тут мастеров больше ))
  • KSergey © (09.02.09 10:24) [17]
    > 123-ий ©   (09.02.09 10:03) [15]
    > смысла то нет, а все тки расскажите. =) интересно

    А  самому подумать? как подсказка - try/except
  • Rouse_ © (09.02.09 10:41) [18]
    А я вот немного не пойму, пример в [0] был тестовый или взятый из "реальной жизни"? Просто зачем создавать промежуточный TStringList если он уже создан в SomeListBox? Может проще брать его оттуда и использовать? Зачем лишние затраты на создание класса и вызов Assign-а при присвоении?
  • {RASkov} © (09.02.09 10:59) [19]
    > [0] 123-ий ©   (09.02.09 07:42)
    > GetSomeList.Free - функция выполняется два раза, а это не оптимально, да и порой неудобно.

    Более того.... Неправильно, ибо память, выделенная в первом вызове, так и утекет в никуда....
  • 123-ий © (09.02.09 11:09) [20]

    > KSergey ©   (09.02.09 10:24) [17]

    дошло уже. :)

    > Rouse_ ©   (09.02.09 10:41) [18]

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

    > {RASkov} ©   (09.02.09 10:59) [19]

    вот вот, оно и выглядело как то странно. действительно, если бы я сразу подумал, ведь вызвав эту функцию два раза, я два раза создам СтрингЛист, а уничтожится он только во второй раз.
  • Anatoly Podgoretsky © (09.02.09 11:23) [21]
    > 123-ий  (09.02.2009 10:03:15)  [15]

    Ввести кроме создания еще и обработку ошибок там же, при ошибке разрушать, если был создан и игнорировать разрушение в процем случае, наружу выдавать nil и возможно исключение.
  • Anatoly Podgoretsky © (09.02.09 11:24) [22]
    > 123-ий  (09.02.2009 11:09:20)  [20]

    Это глупо, если вызван два раза, то и разрушать должен два раза, каждый экземпляр.
  • Palladin © (09.02.09 12:48) [23]

    > Anatoly Podgoretsky ©   (09.02.09 11:23) [21]

    Угу, разрушать в функции создающей, это как гланды вырезать через другой проход.

    Создание - конструктору, инициализация - в безопасном месте.
  • Rouse_ © (09.02.09 12:55) [24]

    > ну как сказать, просто есть один листбокс и несколько функций,
    >  которые должны его заполнять ибо разные функции заполняют
    > его разными данными

    Ну так делай у каждой функции констатарный параметр в который приходит TStrings и пусть они этот TStrings и заполняют, какая разница что это будет, Items или руками созданный TStringList
  • Rouse_ © (09.02.09 13:21) [25]
    Хм... немножко разьясню [24], а то начали в аське переспрашивать :)

    Есть к примеру много листов в которые выводятся данные, так-же есть к примеру 3 процедуры, каждая из которых заполняет листы своими специфическими данными. Как я вижу все это действо: не стоит городить огород с промежуточными TStringList, а стоит написать 3 процедуры вида:

    procedure FillListA(const Value: TStrings);
    var
     I: Integer;
    begin
     Value.Clear;
     // Заполнение данными первого типа
     for I := 0 to Count - 1 do
       Value.Add()
    end;

    // Заполнение данными второго типа
    procedure FillListB(const Value: TStrings)

    // Заполнение данными третьего типа
    procedure FillListC(const Value: TStrings)



    После чего без всяких промежуточных листов вызываем необходимую нам на данным момент процедуру с тем листом, который нужно заполнить:
    FillListA(SomeListBox.Items);



    Вот как-то так...
  • KSergey © (09.02.09 13:25) [26]
    > Rouse_ ©   (09.02.09 13:21) [25]
    > Хм... немножко разьясню [24], а то начали в аське переспрашивать :)

    Это те, кто не смог прочитать [3] и [10]?! Нахрен на них время-то тратить??
  • Palladin © (09.02.09 13:29) [27]
    :)))) и то правда
  • 123-ий © (09.02.09 13:29) [28]

    > Rouse_ ©   (09.02.09 12:55) [24]

    дык я ж написал что так и сделаю в
    > 123-ий ©   (09.02.09 09:27) [7]
    , первая строчка =))
  • Rouse_ © (09.02.09 13:30) [29]

    > Это те, кто не смог прочитать [3] и [10]?! Нахрен на них
    > время-то тратить??

    Видимо не внимательно прочитал :)))) Пардоньте :)
  • 123-ий © (09.02.09 14:07) [30]

    > Видимо не внимательно прочитал :)))) Пардоньте :)

    бывает =)))
  • Anatoly Podgoretsky © (09.02.09 14:38) [31]
    > Palladin  (09.02.2009 12:48:23)  [23]

    Ты вне темы - речь идет об разрушение в случае ошибки.
  • Григорьев Антон © (09.02.09 16:28) [32]

    > Palladin ©   (09.02.09 09:41) [9]
    > Function CreateMyObj:TMyClass;
    > Begin
    >  Result:=TMyClass.Create;
    >  Result.Prop1:=Value1; // предположим, здесь возникает исключение
    > End;

    И в чём проблема?
    function CreateMyObj: TMyClass;
    begin
     Result := TMyClass.Create;
     try
       // Делаем что хотим
     except
       Result.Free;
       raise
     end
    end;

  • Palladin © (09.02.09 16:38) [33]

    > Григорьев Антон ©   (09.02.09 16:28) [32]

    В лишних телодвижениях, зачем нужно отслеживать в отдельном блоке try/except успешность назначения свойств, если гораздо логичней и понятней штатный вызов конструктора и уже далее в try/finally ассигнование свойств. Для себя же пишем. Не смущайте начинающих.
  • KSergey © (09.02.09 17:53) [34]
    > Григорьев Антон ©   (09.02.09 16:28) [32]
    > И в чём проблема?

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

    > 123-ий ©   (09.02.09 11:09) [20]
    > дошло уже. :)

    PS
    Антон, у нас же тут все учителя, разумеется гениальные, так что готовых решений не надо нам :)
  • Городской Шаман (09.02.09 19:23) [35]

    > 123-ий ©   (09.02.09 07:42)  


    Интерфейсы?
  • 123-ий © (10.02.09 06:31) [36]

    > Городской Шаман   (09.02.09 19:23) [35]

    зачем? я вчера вечером переделал в процедуру, которая в параметрах получает Strings. все норм. начиная с поста этак 8 я уже читаю чисто из спортивного интереса.
 
Конференция "Прочее" » Вопрос по уничтожению объектов
Есть новые Нет новых   [134454   +42][b:0][p:0.002]