Re[9]: Вниз и вверх
От: Cyberax Марс  
Дата: 22.02.05 12:12
Оценка:
Кодт пишет:

>>> Мне кажется, достаточно эффективно совмещать все эти подходы, а не

>>> полагаться только на mark-and-sweep.
> C>Проблема будет с GC-объектами, содержащими объекты со счетчиками ссылок
> C>или деструкторами (что мы и имеем в .NET при работе с COMом).
> Не, я имел в виду другое: все объекты являются предметом рассмотрения
> у GC (и нельзя их деструировать в обход). Но!
> Они также ведут счётчик ссылок.

Слишком большой оверхед, особенно для маленьких объектов (счетчик
ссылок, мьютекс).

> И как только он обнуляется, GC немедленно сносит это поддерево, не

> дожидаясь очередного припадка. Тем самым, пул мелких короткоживущих
> объектов не будет переполняться.

Идея хорошая: если при сканировании GC обнаруживает, что один из
древовидных объектов умер — то он просто уничтожает все дерево
подобъектов. Хотя появятся проблемы, если на одного из детей останется
ссылка.

Возможно имел бы смысл вариант, когда пользователь мог бы объявить
некоторые объекты refcount'абельными и использовал бы для их уничтожения
явный деструктор (со всеми вытекающими проблемами).

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[6]: Вниз и вверх
От: _FRED_ Черногория
Дата: 24.02.05 19:07
Оценка:
Здравствуйте, WolfHound, Вы писали:
WH>ИМХО единственное что неверно в его примере эта фраза
WH>// Support this will be supported
WH>которая по видимому должна звучать так
WH>// Suppose this will be supported

Спасибо.

_FR>>Если есть необходимость написать фабрику дочерних классов, то это не представляет никакой трудности, например так:

WH>А если так
WH>  interface Factory<T> { 
WH>    // Use generics type as return type
WH>    T Instance { get; }

WH>    // Or out param 
WH>    // ref (in/out) params will also limit your ability to cast classes
WH>    bool Contruct(out T value); 

WH>    bool Contruct(out T value, T prototype); 
WH>  }


Тогда для экземпляра типа T должна существовать функция вида CopyDataFrom(T prototype), а то я что-то смысла в твоёт варианте Contruct'а на уровне _абстрактной_ фабрики не вижу...
Help will always be given at Hogwarts to those who ask for it.
Re[4]: Вниз и вверх
От: _FRED_ Черногория
Дата: 24.02.05 19:17
Оценка:
Здравствуйте, VladD2, Вы писали:
_FR>>Что-то мне не удалось примеров кода найти... Ткни пожалуйста.
VD>По-моему, что-то было тут http://www.iam.unibe.ch/~scg/Research/Traits/index.html.
Спасибо, но формулировочки там...

VD>>>4. Ввести возможность применения модификатора readonly к параметрам методов и локальным переменным.

_FR>>Угу. Проверять на момент компиляции (как в предлагается здесь
Автор: VladD2
Дата: 08.12.03
) уже хорошо, но надо бы и во время выполнения, а то если сборки перемешаются, концы будет сложно отыскать.

VD>Боюсь, что в рамках дотнета проверки можно будет реализовать тлько в компайлтайме. Но и это уже неплохо. Ведь методы можно будетт помечать атрибутами которые можно и в рантайме проверять. Вот только решение это будет не 100%-ым, так как без поддержки в рантайме будет не просто.
Согласен, уже в качестве средства самоконтроля уже сильно облегчит жизнь.
Кстати, так же, видимо, можно и статические локальные переменные получить на уровне функции?

VD>>>5. Ввести новый тип, разновидность вэлью-типа, позволяющий автоматически вызывать деструкторы (которые тоже ввести для этого типа) при выходе из области видимости.

_FR>>А чем using не удовлетворяет? Только синтаксически?
VD>Тем что являетс необязательным. Ну, и тем что это другой подход. Все же люди привыкли к конструкторам. Откровенно говоря это не так уж необходимо, так как ресурсы почти не досаждают. Но уж если мы косим по С++, то это явно нужно.
Тип данных это уже перебор. Во-первых, "есть правило для FxCop'а", а во-вторых, можно эту фичу и в компилятор (препроцессор) загнать, чтоб обёртывал IDisposable-переменные. И никакого "нового типа"...

VD>>>Возможно еще что-то по мелочи.

_FR>>Не только...
_FR>>Не знаю, насколько это оффтоп в этой ветке, но мне, например, катастрофически не хватет фичи, описанной здесь.
VD>А вот это дурь. Дженерики дотнета намнонго эффективнее Явовских так как умеют работать с вэльютипами. А подобное приведение будет действовать только для ссылочных типов. Да и не заметил я подобной необходимости. В общем, мелоч это. Сделают — хорошо. Нет, ну и ладно.
С приходом дженериков я старался вообще от приведения типов отказаться, а теперь не получится
Help will always be given at Hogwarts to those who ask for it.
Re[6]: Вниз и вверх
От: Gaperton http://gaperton.livejournal.com
Дата: 24.02.05 19:33
Оценка:
Здравствуйте, Шахтер, Вы писали:

Ш>И всё. Объекты перестали удалятся -- потому что нечто, похожее на указатель, лежит в таблице.

Да, правильно, это и есть единственная принципиальная практическая проблема отсутствия метаинформации. +1

Ш>Более того. Если у меня в программе много случайных целых чисел (банальный пример -- буфер с зашифрованными данными), то вероятность подцепить реальный объект становится довольно большой.

От того, что ты подцепишь лишний объект, особых проблем не будет. Главное, не подцепить много лишних объектов.
Это, к счастью, зависит от приложения, и часто проблемой не является. Бороться с этим можно сочетая явный delete с консервативным сборщиком, подбирающим лики.
Re[7]: Вниз и вверх
От: Шахтер Интернет  
Дата: 25.02.05 04:33
Оценка:
Здравствуйте, Gaperton, Вы писали:

G>Здравствуйте, Шахтер, Вы писали:


Ш>>И всё. Объекты перестали удалятся -- потому что нечто, похожее на указатель, лежит в таблице.

G>Да, правильно, это и есть единственная принципиальная практическая проблема отсутствия метаинформации. +1

Ш>>Более того. Если у меня в программе много случайных целых чисел (банальный пример -- буфер с зашифрованными данными), то вероятность подцепить реальный объект становится довольно большой.

G>От того, что ты подцепишь лишний объект, особых проблем не будет.

Если этот лишний объект хранит много ссылок на другие объекты, т.е. например, является контейнером, то будет. Или представь себе дерево. Случайно подцепили его корень -- все узлы подвисли и не удалились вовремя.

G>Главное, не подцепить много лишних объектов.

G>Это, к счастью, зависит от приложения, и часто проблемой не является.

Я вполне допускаю, что есть приложения, для которых это действительно не проблема. Тем не менее, мне не нравится сама идея, что чистота уборки мусора зависит от фаз луны. Нехорошо это.

G>Бороться с этим можно сочетая явный delete с консервативным сборщиком, подбирающим лики.


Есть ещё одна проблема, более серьёзная -- смещённые указатели. Например, создаём объект производного класса и приводим указатель к указателю на базовый класс. Указатель при этом может сместится и указывать теперь внутрь первоначально созданного объекта. Эта ситуация в C++ совсем не редкая. Теперь если первоначальный указатель уйдет, а с объектом мы будем работать через указатель на базовый класс, то возникнет проблема -- этот новый указатель больше не удерживает нужную нам область памяти, что приведет к её досрочному освбождению -- программа загнётся.
... << RSDN@Home 1.1.0 stable >>
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[7]: Вниз и вверх
От: WolfHound  
Дата: 25.02.05 09:44
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Тогда для экземпляра типа T должна существовать функция вида CopyDataFrom(T prototype), а то я что-то смысла в твоёт варианте Contruct'а на уровне _абстрактной_ фабрики не вижу...

Это не суть важно. Важно то что такие конструкции не совместимы с тем что ты хочешь.
... << RSDN@Home 1.1.4 beta 3 rev. 185>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[8]: Вниз и вверх
От: Кодт Россия  
Дата: 25.02.05 10:12
Оценка:
Здравствуйте, Шахтер, Вы писали:

Ш>Есть ещё одна проблема, более серьёзная -- смещённые указатели. Например, создаём объект производного класса и приводим указатель к указателю на базовый класс. Указатель при этом может сместится и указывать теперь внутрь первоначально созданного объекта. Эта ситуация в C++ совсем не редкая. Теперь если первоначальный указатель уйдет, а с объектом мы будем работать через указатель на базовый класс, то возникнет проблема -- этот новый указатель больше не удерживает нужную нам область памяти, что приведет к её досрочному освбождению -- программа загнётся.


Или так:
— создали массив, запомнили указатель на k-й элемент
— создали структуру, запомнили указатель на один из членов

Следовательно, для каждого указателя нужно тем или иным способом определять, внутрь какого блока он указывает.
Перекуём баги на фичи!
Re[8]: Вниз и вверх
От: _FRED_ Черногория
Дата: 25.02.05 11:48
Оценка:
Здравствуйте, WolfHound, Вы писали:
_FR>>Тогда для экземпляра типа T должна существовать функция вида CopyDataFrom(T prototype), а то я что-то смысла в твоёт варианте Contruct'а на уровне _абстрактной_ фабрики не вижу...
WH>Это не суть важно. Важно то что такие конструкции не совместимы с тем что ты хочешь.

То есть и такая, например, конструкция, не имеет права на существование:
    interface IFactory { 
WH>    // Use generics type as return type
WH>    object Instance { get; }

WH>    // Or out param 
WH>    // ref (in/out) params will also limit your ability to cast classes
WH>    bool Contruct(out object value); 

WH>    bool Contruct(out object value, object prototype); 
    }
Help will always be given at Hogwarts to those who ask for it.
Re[9]: Вниз и вверх
От: WolfHound  
Дата: 25.02.05 12:16
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>То есть и такая, например, конструкция, не имеет права на существование:

Тут получишь по башке в рантайме...
... << RSDN@Home 1.1.4 beta 3 rev. 185>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re: Вниз и вверх
От: AVC Россия  
Дата: 25.02.05 14:32
Оценка: 4 (2) +2
Здравствуйте, Кодт, Вы писали:

К>Отвлечёмся от коммерческой стороны вопроса ("что делать с legacy кодом, кто будет переписывать алгоритмы, куда бедным людям податься" итд).


Проблемы с "legacy кодом" мне кажутся надуманными.
Например, программируя на Обероне, можно (хотя бы в XDS Oberon-2) использовать объектники и библиотеки, написанные на других языках (тех же Си и Си++).
Наверное, имеется в виду желание использовать не код, а исходник?

К>Вот язык С++. Что в нём вызывает проблемы и может быть отринуто (для упрощения компилятора, для повышения ошибкоустойчивости и т.д.), что хочется оставить, а что просто необходимо прибавить.


Конечно, можно "поддаться на провокацию" и начать перечислять:
выбросить
— совместимость с Си;
— неопределенность природы указателей (адрес скалярной переменной vs массив? адрес в стеке, сегменте данных или куче?) и адресную арифметику;
— неумеренное использование перегрузки операторов (благодаря чему bool волшебным образом может быть неявно приведен к float)
и т.д.
Добавить
— GC (сразу скажу: опционально).
Но я пока воздержусь, потому что следующий вопрос — самый интересный.

К>Сверхзадача — получить компактный язык, при этом не ломающий навыки С++ников.


Вот это и есть самое интересное и проблемное место в Вашем посте.
В чем именно заключаются навыки Си++ников?
И действительно ли существуют такие навыки, общие для всех, пишущих на Си++?
По моим наблюдениям, на практике Си++ в основном используется как некоторое расширение Си (классы и — реже — шаблоны).
Все, что написано в книгах Александреску, Коплиена и др., — страшно далеко от народа.
Просто люди заняты реальным делом — решением задач, и только между прочим — кодированием. Им некогда (и незачем) изучать этого монстра в полном объеме.
Так какие именно навыки следует оберегать?
Все дальнейшие ответы зависят от ответа на этот вопрос.

К>Интересно, получится ли в результате новая Java, D, или же что-то оригинальное?


Зависит от личного видения проблем Си++.

Но существует одно качество, которое нельзя купить, — это надежность. Цена надежности — погоня за крайней простотой. Это цена, которую очень богатому труднее всего заплатить.

Хоар
Re[5]: Вниз и вверх
От: VladD2 Российская Империя www.nemerle.org
Дата: 25.02.05 15:02
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Кстати, так же, видимо, можно и статические локальные переменные получить на уровне функции?


Мне кажется это делать не нужно. Логику их видимости будет очень не просто объяснить и это усложнит язык. Нельзя забывать, что Шарп создавался как простой в обучении и использовании язык.

Если уж делать нечто подобное, то я бы предпочел ввести локальные области видимости. Например, часто бывает, что в рамках одного класса нужно реализовать некую связанную функциональность. Ну, к примеру, в целях декомпозиции или повторного использования часть кода публичных функций выносится в скрытые методы. По уму такие методы должны быть видны только тем самым публичным методам в которых они используются. Чтобы организовать это можно было бы ввести некие области:
class A
{
    namearea
    {
        public string PublicFuncion1()
        {
            _someStaticWorkVariable++; // OK
            ...
            return SomeWorkFuncion(); // OK
        }
        
        static int _someStaticWorkVariable = 0;
        
        private string SomeWorkFuncion()
        {
            _someStaticWorkVariable++; // OK
            ...
        }
    }

        public string PublicFuncion2()
        {
            _someStaticWorkVariable++; // Error!
            ...
            return SomeWorkFuncion(); // Error!
        }
}


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

_FR>Тип данных это уже перебор. Во-первых, "есть правило для FxCop'а", а во-вторых, можно эту фичу и в компилятор (препроцессор) загнать, чтоб обёртывал IDisposable-переменные. И никакого "нового типа"...


Вот как раз новый тип — это было бы концептуально чистое решение. А разные хаки они и есть хаки. Кроме как к грязи и проблемам такие решения больше ни к чему не приведут.

_FR>С приходом дженериков я старался вообще от приведения типов отказаться, а теперь не получится


Вообще от приведения типов отказаться нельзя. Всегда будут задачи где нужна динамическая типизация и динамический полиморфизм. Количество приведений в основном зависит от грамотности ОО-дизайна приложения. Дженерики же имеют куда больший потенциал нежели средство маскировки приведений типов.
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[8]: Проблемы Conservative GC: 2 Кодт & Шахтер
От: Gaperton http://gaperton.livejournal.com
Дата: 25.02.05 15:23
Оценка:
Здравствуйте, Шахтер, Вы писали:

G>>Главное, не подцепить много лишних объектов.

G>>Это, к счастью, зависит от приложения, и часто проблемой не является.
Ш>Я вполне допускаю, что есть приложения, для которых это действительно не проблема. Тем не менее, мне не нравится сама идея, что чистота уборки мусора зависит от фаз луны. Нехорошо это.

Хорошего мало. Но и к проблемам это приводит редко. Зачем гадать, когда все изученно и померяно, я не понимаю. Ссылки приведены — читай-нехочу.
Advantages and Disadvantages of Conservative Garbage Collection

(1) The collector expands the heap in relatively large chunks, parts of which might never be used, and thus may never need to be in physical memory.
(2) The collector sometimes avoids using certain pages it allocates because it detects integers that appear to point to the page. This also results in allocated virtual memory that is never physically resident.
(3) Memory might appear to be referenced by integers and the like.
(4) Memory might still be referenced through an uncleared pointer even though it was deallocated in the original program.
In early measurements by the author and Zhong Shao, the last two appeared insignificant in practice for most programs, though (4) may occasionally be a factor. More recent measurements by Martin Hirzel and Amer Diwan ( On the Type Accuracy of Garbage Collection, ISMM 2000) are less positive, but also do not show growing leaks through either (3) or (4). Our recent experience still suggests that (3) is typically not a problem, but can become an issue if either the program regularly allocates very large objects, or if the the total size of the collected heap approaches the size of the overall address space. (On 32-bit machines, heap sizes of hundreds of megabytes or gigabytes may be problematic. We have not heard of any issues on 64-bit machines.)


Ш>Есть ещё одна проблема, более серьёзная -- смещённые указатели. Например, создаём объект производного класса и приводим указатель к указателю на базовый класс. Указатель при этом может сместится и указывать теперь внутрь первоначально созданного объекта. Эта ситуация в C++ совсем не редкая. Теперь если первоначальный указатель уйдет, а с объектом мы будем работать через указатель на базовый класс, то возникнет проблема -- этот новый указатель больше не удерживает нужную нам область памяти, что приведет к её досрочному освбождению -- программа загнётся.


Вы думаете, в ЦК дураки сидят? Вот описание алгоритма Boehm GC. http://www.hpl.hp.com/personal/Hans_Boehm/gc/gcdescr.html

А вот вырезка оттуда, которая должна прояснить ситуацию (программа в приведенном примере не загнется). Если хотите половить работающий алгоритм (а не наивную реализацию в уме) — разберитесь с ним.

We determine whether a candidate pointer is actually the address of a heap block. This is done in the following steps:

— The candidate pointer is checked against rough heap bounds. These heap bounds are maintained such that all actual heap objects fall between them. In order to facilitate black-listing (see below) we also include address regions that the heap is likely to expand into. Most non-pointers fail this initial test.
— The candidate pointer is divided into two pieces; the most significant bits identify a HBLKSIZE-sized page in the address space, and the least significant bits specify an offset within that page. (A hardware page may actually consist of multiple such pages. HBLKSIZE is usually the page size divided by a small power of two.)
— The page address part of the candidate pointer is looked up in a table. Each table entry contains either 0, indicating that the page is not part of the garbage collected heap, a small integer n, indicating that the page is part of large object, starting at least n pages back, or a pointer to a descriptor for the page. In the first case, the candidate pointer i not a true pointer and can be safely ignored. In the last two cases, we can obtain a descriptor for the page containing the beginning of the object.
— The starting address of the referenced object is computed. The page descriptor contains the size of the object(s) in that page, the object kind, and the necessary mark bits for those objects. The size information can be used to map the candidate pointer to the object starting address. To accelerate this process, the page header also contains a pointer to a precomputed map of page offsets to displacements from the beginning of an object. The use of this map avoids a potentially slow integer remainder operation in computing the object start address.
— The mark bit for the target object is checked and set. If the object was previously unmarked, the object is pushed on the mark stack. The descriptor is read from the page descriptor. (This is computed from information GC_obj_kinds when the page is first allocated.)

Re[10]: Вниз и вверх
От: Gaperton http://gaperton.livejournal.com
Дата: 25.02.05 19:18
Оценка: :)))
Ш>
Ш>uintptr_t var;

Ш>void fun(Object *ptr)
Ш> {
Ш>  var=(uintptr_t)ptr;
Ш> }
Ш>


Ш>Будет ли var удерживать ptr? Без подсказки со стороны программиста ничего сказать нельзя. Т.е. нужны или дополнения в язык, которые позволили бы разруливать такие ситуации, или использование определённых соглашений.


Я не понимаю, в чем проблема. Это С++. Программирование на С++ небезопасно, если не соблюдать технику безопасности (определенные соглашения). Это относится ко всему языку, и добавлением сборщика мусора ничего не исправляется. Да, сборщик мусора, как и все в С++, будет работать нормально только при использовании специальных соглашиний.

И что это доказывают эти 25 способов настипить себе на ..., я не понимаю? То, что консервативный GC можно сломать? То, что он бесполезен? То, что это не GC? Или то, что он оставляет немного неосвобожденной памяти (которая и без GC чуть-чуть утекает )?

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

В одной из историй про Дарвиновские премии, главный герой пописал на работающий промышленный трансформатор. Он сделал это неумышленно.
Re[9]: Проблемы Conservative GC: 2 Кодт & Шахтер
От: Шахтер Интернет  
Дата: 26.02.05 03:36
Оценка:
Здравствуйте, Gaperton, Вы писали:

G>Здравствуйте, Шахтер, Вы писали:


G>>>Главное, не подцепить много лишних объектов.

G>>>Это, к счастью, зависит от приложения, и часто проблемой не является.
Ш>>Я вполне допускаю, что есть приложения, для которых это действительно не проблема. Тем не менее, мне не нравится сама идея, что чистота уборки мусора зависит от фаз луны. Нехорошо это.

G>Хорошего мало. Но и к проблемам это приводит редко.


Есть две философии программирования. Согласно одной, программа должна вести себя корректным образом. Согласно другой, если в программе возникают ошибки (редко) -- ну и фиг с ним. Кнопка ресет всегда под рукой.

G>Зачем гадать, когда все изученно и померяно, я не понимаю. Ссылки приведены — читай-нехочу.

G>Advantages and Disadvantages of Conservative Garbage Collection
G>

G>(1) The collector expands the heap in relatively large chunks, parts of which might never be used, and thus may never need to be in physical memory.
G>(2) The collector sometimes avoids using certain pages it allocates because it detects integers that appear to point to the page. This also results in allocated virtual memory that is never physically resident.
G>(3) Memory might appear to be referenced by integers and the like.
G>(4) Memory might still be referenced through an uncleared pointer even though it was deallocated in the original program.
G>In early measurements by the author and Zhong Shao, the last two appeared insignificant in practice for most programs, though (4) may occasionally be a factor. More recent measurements by Martin Hirzel and Amer Diwan ( On the Type Accuracy of Garbage Collection, ISMM 2000) are less positive, but also do not show growing leaks through either (3) or (4). Our recent experience still suggests that (3) is typically not a problem, but can become an issue if either the program regularly allocates very large objects, or if the the total size of the collected heap approaches the size of the overall address space. (On 32-bit machines, heap sizes of hundreds of megabytes or gigabytes may be problematic. We have not heard of any issues on 64-bit machines.)


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

Ш>>Есть ещё одна проблема, более серьёзная -- смещённые указатели. Например, создаём объект производного класса и приводим указатель к указателю на базовый класс. Указатель при этом может сместится и указывать теперь внутрь первоначально созданного объекта. Эта ситуация в C++ совсем не редкая. Теперь если первоначальный указатель уйдет, а с объектом мы будем работать через указатель на базовый класс, то возникнет проблема -- этот новый указатель больше не удерживает нужную нам область памяти, что приведет к её досрочному освбождению -- программа загнётся.


G>Вы думаете, в ЦК дураки сидят? Вот описание алгоритма Boehm GC. http://www.hpl.hp.com/personal/Hans_Boehm/gc/gcdescr.html


Господи, да читали мы всё это, читали. Дураки сидят в ЦК, ага.

G>А вот вырезка оттуда, которая должна прояснить ситуацию (программа в приведенном примере не загнется). Если хотите половить работающий алгоритм (а не наивную реализацию в уме) — разберитесь с ним.


Может, для начала разберётесь сами?

G>

G>We determine whether a candidate pointer is actually the address of a heap block. This is done in the following steps:

G>- The candidate pointer is checked against rough heap bounds. These heap bounds are maintained such that all actual heap objects fall between them. In order to facilitate black-listing (see below) we also include address regions that the heap is likely to expand into. Most non-pointers fail this initial test.
G>- The candidate pointer is divided into two pieces; the most significant bits identify a HBLKSIZE-sized page in the address space, and the least significant bits specify an offset within that page. (A hardware page may actually consist of multiple such pages. HBLKSIZE is usually the page size divided by a small power of two.)
G>- The page address part of the candidate pointer is looked up in a table. Each table entry contains either 0, indicating that the page is not part of the garbage collected heap, a small integer n, indicating that the page is part of large object, starting at least n pages back, or a pointer to a descriptor for the page. In the first case, the candidate pointer i not a true pointer and can be safely ignored. In the last two cases, we can obtain a descriptor for the page containing the beginning of the object.
G>- The starting address of the referenced object is computed. The page descriptor contains the size of the object(s) in that page, the object kind, and the necessary mark bits for those objects. The size information can be used to map the candidate pointer to the object starting address. To accelerate this process, the page header also contains a pointer to a precomputed map of page offsets to displacements from the beginning of an object. The use of this map avoids a potentially slow integer remainder operation in computing the object start address.
G>- The mark bit for the target object is checked and set. If the object was previously unmarked, the object is pushed on the mark stack. The descriptor is read from the page descriptor. (This is computed from information GC_obj_kinds when the page is first allocated.)


Тут уж одно из двух. Или вы проверяете на совпадение с началом блока, но тогда пропускаете смещённые указатели. Либо проверяете попадание внутрь блока, но тогда вероятность зацепить его случайным целым (и не только целым), особенно если в программе есть буфера с псевдослучайными данными, будет достаточно велика, и будет лик. Короче или нос в дерьме, или хвост в вазелине.

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

А вообще, все эти попытки построения GC в C++ напоминают попытки построения вечного двигателя.
... << RSDN@Home 1.1.0 stable >>
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re: Вниз и вверх
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 27.02.05 20:25
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Сверхзадача — получить компактный язык, при этом не ломающий навыки С++ников.

К>Дополнительные пожелания: минимизировать рантайм (или сделать его гибко настраиваемым: в частности, сборка мусора — может ли быть опциональной, как RTTI, или же просто обязана быть в ядре?)

Вот, после выходного дня, наполненого праздным безделием , появилась идейка по поводу управления динамической памятью в С++:

В C++ проблемы с new/delete, ИМХО, заключаются не в том, что для каждого new нужно вызывать delete. В конце-концов, в Java и C# так же нужно занулять ссылки на уже не нужные объекты, чтобы избежать утечек памяти. Проблема в том, что:

— delete можно вызывать только для указателя, который был получен с помощью new. Применение, например, delete к указателю на размещенную в стеке переменную ни к чему хорошему не приведет;

— delete можно применять к одному и тому же указателю только один раз;

— применяя delete к указателю программист лишен возможности узнать, не использует ли этот указатель кто-то еще. Т.е. программист должен быть в этом уверен. Но уверенность эта должна исходить из особенностей его алгоритма, а не со стороны каких-то возможностей языка С++.

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

Может быть идея и дикая. Но, мне кажется, что она позволит мне проще обращаться с указателями. Действительно, получая указатель на что-либо, я вызываю для него delete просто для того, чтобы сказать: "Этот указатель мне больше не нужен". На что run-time должен ответить: "Ok, не нужен, так не нужен". И далее: "Эта память освободилась, сделаем ее свободной". Или: "Это вообще не динамический объект, а локальная переменная, со временем она сама умрет". Или: "Этот объект нужен еще кому-то кроме тебя, пусть поживет пока". Т.е. обязаности вызывать delete для каждого new с меня никто не снимает. Просто мне гарантируют, что delete примененный для валидного указателя, не приведет к проблемам в описанных выше случаях.

Честно говоря, я не знаю, можно ли это реализовать вообще и если можно, то в какие накладные расходы это выльется. Не спец я в таких вопросах. Но, ИМХО, жизнь мне такая фишка упростила бы.
... << RSDN@Home 1.1.4 beta 3 rev. 185>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[4]: Вниз и вверх
От: DJ KARIES Россия  
Дата: 06.03.05 15:13
Оценка:
Здравствуйте, McSeem2, Вы писали:

MS>Так вот, любой язык — это всегда компромис между выразительными возможностями и строгостью. На Эсперанто написать поэму — получится скучно и невыразительно. Аналогичные проблемы возникают и с концептуально чистыми языками программирования — они просто скучны. Где фантазия? Где — полет мысли? Один сплошной "технологический процесс". А программист при этом просто стоит у станка и занимается совершенно тупой работой — распускает доски на брус. А я хочу быть мастером-краснодеревщиком и создавать красоту.

Вы, значит, батенька, тут кучерявым инструментом "создаёте красоту", а мы, скучные юзеры, потом трахайся с вашей шаблонной "красотой" "Вниз и вверх"...
ntr soft: www.dkdens.narod.ru :: giref: www.retroforth.org/board/index.php?topic=177.0
Re[2]: Вниз и вверх
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 21.03.05 16:23
Оценка:
Здравствуйте, eao197, Вы писали:

E>Здравствуйте, Кодт, Вы писали:


К>>Сверхзадача — получить компактный язык, при этом не ломающий навыки С++ников.

К>>Дополнительные пожелания: минимизировать рантайм (или сделать его гибко настраиваемым: в частности, сборка мусора — может ли быть опциональной, как RTTI, или же просто обязана быть в ядре?)

E>Вот, после выходного дня, наполненого праздным безделием , появилась идейка по поводу управления динамической памятью в С++:


E>В C++ проблемы с new/delete, ИМХО, заключаются не в том, что для каждого new нужно вызывать delete. В конце-концов, в Java и C# так же нужно занулять ссылки на уже не нужные объекты, чтобы избежать утечек памяти. Проблема в том, что:


E>- delete можно вызывать только для указателя, который был получен с помощью new. Применение, например, delete к указателю на размещенную в стеке переменную ни к чему хорошему не приведет;


E>- delete можно применять к одному и тому же указателю только один раз;


E>- применяя delete к указателю программист лишен возможности узнать, не использует ли этот указатель кто-то еще. Т.е. программист должен быть в этом уверен. Но уверенность эта должна исходить из особенностей его алгоритма, а не со стороны каких-то возможностей языка С++.


Вот высказал когда-то эту идею, но, к сожалению, никто ничего по этому поводу не сказал. А недавно в форуме C/C++ появились две похожие ветки: Проверка указателя на объект после его деструктора
Автор:
Дата: 21.03.05
и RTTI и разрушенные объекты
Автор: Leshi
Дата: 19.03.05
.

У меня самого высказанная выше идея появилась после того, как я прочитал про ACE_Event_Handler из библиотеки ACE. Там обычной практикой является написание собственного handler-а (производного от ACE_Event_Handler) и уничтожение его в методе handle_close через delete this. Такой подход к делу мне не понравился по двум причинам:

1. Такие handler-ы не могут быть созданы на стеке или как глобальные/статические объекты, поскольку они будут пытаться вызвать delete для указателя, который не был динамически распределен.

2. При наследовании от таких handler-ов нужно точно знать, что, когда и как они делают. Что не всегда возможно. Но даже, если знаешь, что базовый класс удаляет себя в handle_close, то что делать, если тебе так же нужно перекрыть handle_close? Не вызывать метод handle_close из базового класса и все переписывать самому? Или что делать, если есть необходимость создать шаблонный класс, параметром которого будет класс handler-а. И в одних handler-ах delete в обработчиках вызывается, а в других нет?

Вот мне и подумалось, что если разрешить повторно делать delete для уже удаленного объекта, то при использовании ACE было бы меньше проблем. Например, можно было бы писать так:

class    My_Derived_Handler : public My_Base_Handler
    {
    public :
        virtual int    handle_close( ACE_HANDLE h, ACE_Reactor_Mask m )
            {
                My_Base_Handler::handle_close( h, m );
                delete this;
                return 0;
            }
    };


Ну, а все остальные предложения стали развитием этой мысли.



Я понимаю, что проблема здесь не столько в C++, сколько в ACE. Но все же... Раз речь зашла о возможных направлениях развития C++, то почему бы и нет?
... << RSDN@Home 1.1.4 beta 4 rev. 303>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[2]: Вниз и вверх
От: _wqwa США  
Дата: 22.03.05 09:47
Оценка:
Здравствуйте, eao197, Вы писали:


E>Честно говоря, я не знаю, можно ли это реализовать вообще и если можно, то в какие накладные расходы это выльется. Не спец я в таких вопросах. Но, ИМХО, жизнь мне такая фишка упростила бы.


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

Эти вещи реализованы в Obj-C и должен признать, что такие мелючи не окупают возможностей, которые дает С++
... << RSDN@Home 1.1.4 beta 4 rev. 303>>
Кто здесь?!
Re[3]: Вниз и вверх
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 22.03.05 13:53
Оценка:
Здравствуйте, _wqwa, Вы писали:

_>Здравствуйте, eao197, Вы писали:



E>>Честно говоря, я не знаю, можно ли это реализовать вообще и если можно, то в какие накладные расходы это выльется. Не спец я в таких вопросах. Но, ИМХО, жизнь мне такая фишка упростила бы.


_>То что ты описал -- выглядит один в один, как подсчет ссылок + игнорирование вызова методов у несуществующего экземпляра.

_>Первое решается легко, и давно решено, второе -- даст небольшой выигрыш, но совершенно несравнимый со сборкой мусора.

Имхо, на подсчет ссылок оно вообще не похоже. Т.к. в некоторых случаях я нигде указателей не сохраняю. Например, когда выполняю delete this. Не говоря уже о возможности безопасного применения delete к объектам на стеке.
Так же я не думаю, что подсчет ссылок -- это простая штука. Особенно при наличии циклических связей.

Ну и вообще, не думаю, что сборка нужна в C++. Есть куча языков, в которых сборка мусора реализована. Имхо, не нужно C++ в них превращать.
... << RSDN@Home 1.1.4 beta 4 rev. 303>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[4]: Вниз и вверх
От: _wqwa США  
Дата: 23.03.05 07:31
Оценка:
Здравствуйте, eao197, Вы писали:



E>>>Честно говоря, я не знаю, можно ли это реализовать вообще и если можно, то в какие накладные расходы это выльется. Не спец я в таких вопросах. Но, ИМХО, жизнь мне такая фишка упростила бы.


_>>То что ты описал -- выглядит один в один, как подсчет ссылок + игнорирование вызова методов у несуществующего экземпляра.

_>>Первое решается легко, и давно решено, второе -- даст небольшой выигрыш, но совершенно несравнимый со сборкой мусора.

E>Имхо, на подсчет ссылок оно вообще не похоже. Т.к. в некоторых случаях я нигде указателей не сохраняю. Например, когда выполняю delete this. Не говоря уже о возможности безопасного применения delete к объектам на стеке.

E>Так же я не думаю, что подсчет ссылок -- это простая штука. Особенно при наличии циклических связей.

E>Ну и вообще, не думаю, что сборка нужна в C++. Есть куча языков, в которых сборка мусора реализована. Имхо, не нужно C++ в них превращать.


Хорошо, начнем сначала: оригинальные утверждения:

— delete можно вызывать только для указателя, который был получен с помощью new. Применение, например, delete к указателю на размещенную в стеке переменную ни к чему хорошему не приведет;

— delete можно применять к одному и тому же указателю только один раз;

— применяя delete к указателю программист лишен возможности узнать, не использует ли этот указатель кто-то еще. Т.е. программист должен быть в этом уверен. Но уверенность эта должна исходить из особенностей его алгоритма, а не со стороны каких-то возможностей языка С++.


1. лечится ампутацией . Запретить экземпляры на стеке, и всего-то делов.
2. То, о чем я говорил, игнорирование вызова методов у несуществующего экземпляра, довольно просто реализуется
3. Разве это не подсчет ссылок?

Впрочем, я утрировал. Особенно, насчет п. 1. Если вопрос стоит в накладных расходах, то п. 3 -- можкт обойтись сравнительно дешево, если его делать просто подсчетом ссылок, если же отслеживать просто, чтобы к-во ссылок было больше одной, то это, наверно, сложнее... Я пока даже не соображу как
... << RSDN@Home 1.1.4 beta 4 rev. 303>>
Кто здесь?!
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.