Войти
ПрограммированиеФорумОбщее

Вопросы по Delphi (37 стр)

Страницы: 136 37 38 3956 Следующая »
#540
(Правка: 2:11) 2:09, 7 авг 2022

MrShoor
> кого? local?
вот такой случай

procedure Foo(obj: TMyObject);
begin
  obj.Free;
end;

var
obj1: TMyObject local;
begin
  obj1 := TMyObject.Create;
  Foo(obj1); 
end; // падаем здесь из-за двойного удаления

и никто ничего в этом случае не скажет

для managed типов, это вообще не проблема.

#541
(Правка: 3:00) 2:44, 7 авг 2022

MrShoor
> ничего не течет.
/facepalm
Даже дока раста почти честно пишет, врут только про "на практике". (где исследования этой практики? это не "на практике", а "по нашему мнению", наглая подмена понятия)
https://doc.rust-lang.org/nomicon/leaking.html

Many people like to believe (мое примечание: эффект пропаганды!) that Rust eliminates resource leaks. In practice, this is basically true. You would be surprised to see a Safe Rust program leak resources in an uncontrolled way.

However from a theoretical perspective this is absolutely not the case (мое примечание: как на самом деле!), no matter how you look at it. In the strictest sense, "leaking" is so abstract as to be unpreventable.

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

>Тебе всё равно либо придется их грохать по одному, либо грохать всё приложение
Ты точно настаиваешь что любой объект нужно обязательно грохать по одному?
Скажем есть дерево C++ объектов у которых несколько полей std::string-ов, созданных временно и нужных только до конца работы алгоритма?
И никак, абсолютно никак невозможно грохнуть дерево узлов с кучей строковых полей в каждом одним вызовом free?

#542
3:00, 7 авг 2022

skalogryz
> вот такой случай
Ну то есть некоторая функция Foo. Ты знаешь, что когда ты туда отдаешь указатель - владение переходит к ней, и она сделает Free. По хорошему параметр такой функции должен быть объявлен как:

procedure Foo(obj: TMyObject local);

и в имплементации никакого Free быть не должно.
Но допустим это старый код и функция не объявлена с параметром local. Поэтому просто нужен механизм, чтобы можно из local отдать значение, что-то в духе:

var
obj1: TMyObject local;
obj2: TMyObject;
begin
  obj1 := TMyObject.Create;
  obj2 := obj1.Detach; //здесь в obj2 записывается указатель на объект
                //а потом obj1 обнуляется не вызывая деструктор
end;

Ну и в твоем случае это будет:

procedure Foo(obj: TMyObject);
begin
  obj.Free;
end;

var
obj1: TMyObject local;
begin
  obj1 := TMyObject.Create;
  Foo(obj1.Detach); 
end; // всё, никто никуда не падает

Но опять же, акцентирую внимание, что функция Foo дожна быть написана с local. И Free руками звать вообще не надо.

#543
3:10, 7 авг 2022

CD
> "Предотвратить утечки в теории абсолютно невозможно, но на практике мы это
> делаем, мамой клянемся."
А сделать утечку без Unsafe кода на Rust ты можешь? Написать хоть один пример? Или только на форуме писать, что "всё ложь"?

> Скажем есть дерево C++ объектов у которых несколько полей std::string-ов,
> созданных временно и нужных только до конца работы алгоритма?
> И никак, абсолютно никак невозможно грохнуть дерево узлов с кучей строковых
> полей в каждом одним вызовом free?
А у тебя есть простой способ, как корректно освободить память одним куском, чтобы деструкторы std::string-ов не вызывались? Мне разве что на ум приходит единственный путь: сделать кастомный аллокатор, сделать утечку всего дерева, грохнуть кастомный аллокатор. Но это прямой путь отстрелить не только ногу, но и руку, а так же ногу соседа, и рекошетом еще убить кошку на крыше.

#544
3:55, 7 авг 2022

MrShoor
> А сделать утечку без Unsafe кода на Rust ты можешь? Написать хоть один пример?
> Или только на форуме писать, что "всё ложь"?

Эм. Ну как бы в доке раста по ссылке есть тривиальные примеры? Думаешь не осилю, или есть какие-то дополнительные требования к коду? Если есть, тогда сначала дополнительные требования в студию.


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

Кошку конечно жалко, но то что RAII провоцирует освобождение временных объектов за O(n) вместо O(1) это тоже важно. Обмен должен быть осознанным, а любители RAII про такое не пишут.

std::string это был пример для O(n), для O(1) первым делом приходит в голову string_view указывающий на арену.

#545
4:09, 7 авг 2022

CD
> Думаешь не осилю, или есть какие-то дополнительные требования к коду?
Требования только одно, не использовать unsafe. Если какая-то внешняя библиотека возвращает что-то - это unsafe. Даже если это u32 как в случае с OpenGL например.

> std::string это был пример для O(n), для O(1) первым делом приходит в голову
> string_view указывающий на арену.
Ясно, твой пример был мимо кассы. RAII тут не причем, просто меняй способ обработки данных, сложи всё в один массив, работай с указателями на этот массив и грохай за один вызов. RAII тебе это как бы не запрещает делать, и string_vew - явное тому подтверждение.

#546
5:49, 7 авг 2022

MrShoor
> Но опять же, акцентирую внимание, что функция Foo дожна быть написана с local.
> И Free руками звать вообще не надо
про аргументы с local

1. оке. будет освобождён

Foo(obj: Tobject local)

2. оке. будет освобождён, на выходе - гарантируемый nil

Foo(var obj: Tobject local)

3. нельзя. т.к. значение nil не присвоится

Foo(const obj: Tobject local)
#547
6:23, 7 авг 2022

skalogryz
> 1. оке. будет освобождён
> Foo(obj: Tobject local)
Да

> 2. оке. будет освобождён, на выходе - гарантируемый nil
> Foo(var obj: Tobject local)
Нет. В данном случае освобожден не будет, т.к. это ссылка на внешнюю переменную. Освобожден он будет только в случае присвоения в эту переменную:

Foo(var obj: Tobject local);
begin
  obj := nil; // или obj := Tobject.Create; но в этом случае в obj будет новый объект
end;

skalogryz
> 3. нельзя. т.к. значение nil не присвоится
> Foo(const obj: Tobject local)
Не должно компилироваться.

#548
(Правка: 8:26) 7:33, 7 авг 2022

В Delphi вариант с автоматической зачисткой, имхо, напрашивается сам собой.
Надо просто вспомнить как реализована автоматическая зачистка строк и динамических массивов.
Банальный рефкаунтинг на уровне языка.
Интерфейсы для COM-объектов реализуют то же самое.
Надо просто перенести функционал на обычные объекты.
Допустим в TObject будет еще поле recCount: Cardinal и присваивания тупо его используют для переменных которые помечены особым образом.
Вот каким образом - вопрос.
Может закорючкой какой типа obj: @TObject, где собачка имитирует букву automatic.
В сущности в плюсах ничего умнее и не придумали, только пытаясь эту семантику натянуть на любой объект как обычно наворотили шиворот граблей с make_shared_from_this и make_shared.
А в Delphi ничего такого городить не надо - TObject уже есть и от него все наследуют, рефкаунт в него же грех не положить. Объекты всегда создаются в куче, имеют ссылочную семантику, поэтому всё что требуется - это ссылки особого, рефкаунтного вида, а не какие то пляски с автодеструкторами или move-семантиками.
Квадрактиш, практиш, гут.
Но особо никому не надо.

#549
(Правка: 9:01) 8:43, 7 авг 2022

=A=L=X=
там сделали, но криво - только для мобильных осей, и при этом для всех объектов без выбора. В итоге чтоб написать программу надо было минусы обоих подходов собирать - и Free не забывать (чтоб память не текла под виндой) и [Weak] расставлять (чтоб память не текла на андроиде).

и кстати на андроиде утечки мне больше проблем доставляли. Так то если забыл free, то в дебаг редиме в конце выполнения тебе дельфи покажет сколько каких обьектов не удалено, так что берешь и находишь где ты free забыл. А в андроиде я так и не понял где текло, вроде на стыке недр fmx и Java кода. Так что поиходилось говорить "ну вы просто перезагружайте пульт когда индикатор стал красным, пока мы вам на нормальный пульт с виндой не поменяем".

Я так понимаю это никому не нравилось и в версии 10.4 от этого отказались и вернули как было раньше.
нагугуглилось https://blog.marcocantu.com/blog/2018-october-Delphi-ARC-directions.html
оказывается могли бы и на все оси распостранить, но не осилили расстановку weak для легаси кода, ну и пишут что не смогли заставить сосуществовать ARC и обычные обьекты в одном контейнере.

#550
9:01, 7 авг 2022

kipar

О, в XE оказывается догадались наконец то сделать интерфейсам модификатор [weak]. Вот почему об этом не подумали когда их делали еще в в первой самой версии - уму непостижимо. Судя по статье штатный способ был всё это время - хранить в Pointer. Ну маразм же для языка такого уровня.
В общем то гладко делали, то в какой то маразм впадали. В том числе и с таким инвазивным refCount тоже.

#551
(Правка: 13:01) 12:10, 7 авг 2022

MrShoor
> Требования только одно

fn gameloop()
{
    loop
    {        
    }
}
fn main() {
    //{
        let mut vec = Vec::new();
        for i in 1..25_000_000 
        {
            vec.push(i);
        }
    //} ой, я забыл скобочки, теперь временные 100MB аллоцированных при загрузке игры утекло
    gameloop();
}

>RAII тут не причем, просто меняй способ обработки данных

Ага, замена RAII на управление памятью другим способом, и RAII оказывается не причем. Бывает.

#552
18:43, 7 авг 2022

=A=L=X=
> Судя по статье штатный способ был всё это время - хранить в Pointer.
Такой себе способ, ибо если интерфейс сливался, то Pointer по прежнему содержал указатель на интерфейс, но только у тебя уже не было способа определить, ссылается ли он на валидный объект или нет. В случае с [weak] если интерфейс сливается, то такой указатель становится равным nil.

CD
> //} ой, я забыл скобочки, теперь временные 100MB аллоцированных при загрузке
> игры утекло
Всмысле утекло? Оно не утекло, т.к. будет очищено при выходе из области видимости. Сделай имплементацию Drop и увидишь, что все деструкторы вызываются. Ты сейчас пытаешься выдать за утечку то, что не является утечкой.
Ок, давай уточним. Утечка - это то, что не удаляется самим Rust-ом, а удаляется непосредственно средствами операционной системы когда процесс завершается. Проверить удаляет ли Rust - легко. Делаешь имплементацию Drop, и если Rust не позовет Drop до самого завершения программы, значит он не удалил объект.
Так что, сможешь предоставить пример с настоящей утечкой без unsafe кода в Rust?

#553
(Правка: 19:16) 19:14, 7 авг 2022

MrShoor
> Ок, давай уточним. Утечка - это то, что не удаляется самим Rust-ом, а удаляется
> непосредственно средствами операционной системы когда процесс завершается.

С козырей зашел: "когда вы забываете освободить память, то это утечка, кроме случаев когда вы пишете на расте без unsafe, тогда разрешаю это утечкой не считать".

Мне что, процитировать определение утечки с википедии? На, держи:

In computer science, a memory leak is a type of resource leak that occurs when a computer program incorrectly manages memory allocations[1] in a way that memory which is no longer needed is not released.

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

Документация раста, кстати, считает также.

#554
(Правка: 20:23) 20:21, 7 авг 2022

CD
> Память не нужна, память не освобождена - можно поглядеть в диспетчере задач.
> Все просто - это настоящая утечка.
Всё ясно. Тогда у тебя и тут утечка:

A a = new A();
std::cout<<"Hello World\n"; //Ааааа! Память объекта 'a' не нужна, и не освобождена. Утечка! Аааа!
delete a;

Считаю на этом можно заканчивать. Ты про утечки что-то там себе нафантазировал, что к реальным проблемам не относится. Показать реальную утечку (которую описал я выше) без unsafe ты не смог.

Страницы: 136 37 38 3956 Следующая »
ПрограммированиеФорумОбщее