тождество - это абсолютное соответствие одной сущности другой, поэтому 0 типа чар не тождественнем 0 типа инт
внутри подмножества более узкие рамки. Потому, если записать в rax char=0, и в rdx int=0, то содержимое rdx,rax будет тождественно равно. Отличие есть, но оно осталось ЗА рамками подмножества, и внутри подмножества мы имеем тождество.
Кстати, нулевые константы в сишечки тоже тождественно равны, если это не NULL.
грабли есть везде. Есть они и в C++, причём их там тоже немало. Почему ты смеёшься, когда жабообезьяны наступают на грабли C++, а сам плачешь, когда наступаешь на грабли какого-то питона?
то, что он тяжело читается, нельзя так код писать
это безусловно говнокод, но фича в том, что он ВСЕГДА выполняется ОДИНАКОВО. Если тебе нужен хоть какой-то код, и есть только обезьяны, то ничего не поделаешь...
1. Поищи на форуме тут кот-то портировал программу на ахитектуру с 16-битным char. И не надо выдумывать про несоответствие стандарту компиляторов под архитектуры, про которые не знаешь.
Нельзя в крестах сделать полноценный сборщик, даже если придумать умные указатели. Ты их при сборке не найдешь. Если только еще завести свои объекты, тогда можно хотя бы филды находить. еще можно хранить отдельно список ссылок, лажащих на стеке. это максимум. и это плохой и тормозной сборщик.
Проблема в том, что для mark & sweep нужно не только знать какие объекты выделены под сборку (это можно было бы решить просто помещая все собираемые объекты в отдельную кучу, например), но и какие объекты в настоящий момент ни в коем случае собирать нельзя (их я собственно и называл корневыми). Обычно это глобальные объекты и объекты ссылки на которых есть на стеке. Все корневые объекты по умолчанию доступны. Затем GC рекурсивно помечает доступными все объекты на которые есть ссылки из уже доступных объектов. После все не помеченные объекты он освобождает. Так вот в плюсах основная проблема это определение списка корневых объектов.
Обычно это глобальные объекты и объекты ссылки на которых есть на стеке. <..> Так вот в плюсах основная проблема это определение списка корневых объектов.
так вот: не делай глобальных объектов и объектов на стеке. Если ты их сделал внутри class::new — ты ССЗБ.
ну так предложи алгоритм. чего зря болтаешь? я делал для с++ сборщики с различными стратегиями. полноценно сделать это невозможно. полноценному сборщику нужна метаинформация, карта ссылок объекта, карта рутовых объектов. в jvm и clr этим занимаются компилятор и jit.
на стеке ссылки на объекты, а не сами объекты. тебе нужно понять, какие объекты доступны из кода. изначально это глобальные объекты и объекты на стеке каждой треды. это рутовые ссылки. потом ты идешь по полям объектов, доступных по этим ссылкам, определяя объекты, доступные из доступных объектов и т.д. пока не обойдешь все. как ты это сделаешь на крестах? или опиши аналог. в любом слцчае, набросай алгоритм
я делал для с++ сборщики с различными стратегиями. полноценно сделать это невозможно. полноценному сборщику нужна метаинформация, карта ссылок объекта, карта рутовых объектов. в jvm и clr этим занимаются компилятор и jit.
ты лучше расскажи, почему и что у тебя не получилось в C++?
GC работает НЕ со ссылками, и НЕ с объектами, а с СОДЕРЖИМЫМ объектов. Ну например у тебя есть объект string, а ВНУТРИ него указатель на строку char *string_ptr;. Вот GC работает с string_ptr, а он ВСЕГДА в куче, как в твоей яве. Ты его просто НЕ МОЖЕШЬ сделать не в куче, ибо он private, и доступ к нему ТОЛЬКО через методы.
ты лучше расскажи, почему и что у тебя не получилось в C++?
Я не он, но думаю, что трудность тут как раз в построении карты объектов. В языках с нормальным рантаймом этим занимается jit по той метаинформации, что оставил для него компилятор. В С++ этого всего нет(может быть в llvm разве что, в libjit вроде не видел).
Ну например у тебя есть объект string, а ВНУТРИ него указатель на строку char *string_ptr;. Вот GC работает с string_ptr, а он ВСЕГДА в куче, как в твоей яве. Ты его просто НЕ МОЖЕШЬ сделать не в куче, ибо он private, и доступ к нему ТОЛЬКО через методы.
Ну и что, что данные в куче? Этого мало для того, чтобы понять, мусор он или нет.
Как это пуст? Это список не мусора, а список доступных объектов.
для тех кто в танке: ВСЕ объекты в списке GC лежат в куче.
Разве сложно распарсить это простое предложение?
причём является мусором, если больше его никто не использует.
Как определить, используют его или нет?
в данном случае
X = Y;
тем же самым operator=(). Вот тут оно не только отправляет в мусор (потенциальный) старое содержимое X, но и ещё кроме того, определяет, что содержимое Y используется не только самим Y, но и теперь X. Потому, если дальше
Y = Z;
то GC, когда запустится, НЕ удалит старое Y, ибо оно используется ещё и X.
В самом простом случае достаточно счётчика ссылок, который для Y в начале равен 1, а вот после
X = Y;
будет равен 2.
Ну а для X, после этой же операции, счётчик ссылок декрементируется.
ВАЖНО: это ОДНА ИЗ реализаций, самая простая, на пальцах. Можно юзать любую иную тактику и/или стратегию.
Я не он, но думаю, что трудность тут как раз в построении карты объектов. В языках с нормальным рантаймом этим занимается jit по той метаинформации, что оставил для него компилятор. В С++ этого всего нет
Верно. В C++ искороппки имеется тупой operator=(), который тупо побитно копирует весь объект.
Но это вовсе не значит, что этот operator=() нельзя перезагрузить. Можно. И нужно. Даже если ты его не используешь.
Ну и что, что данные в куче? Этого мало для того, чтобы понять, мусор он или нет.
они не просто в куче, они вообще ЗАКРЫТЫ. Ты не можешь на них влиять напрямую. Можешь только косвенно, например через метод operator=(). Вот этот-то метод и сохраняет информацию о том, что есть мусор, а что не мусор.
Основная идея сборщика мусора в том, чтобы делегировать поиск и удаление невостребованных объектов отдельному самостоятельному «модулю», который никак не взаимодействует с логикой работы самого приложения и является частью исполняющей среды. Основная проблема сборщика мусора - поиск объектов, которые доступны(или, наоборот, недоступны). Вот вас тут и спрашивают, каким вы видите алгоритм поиска доступных объектов в сборщике для С++. Boehm ищет в «памяти»(в стеке каждого потока, в регистрах, в статической памяти, в куче, в собственной куче) слова, значение которых совпадает с диапазоном адресов выделенных boehm'ом объектов. И помечает эти объекты как используемые. Остальные объекты в своей куче считает мусором. Это работает, но имеет ряд существенных недостатков. Во-первых, мы можем принять за ссылку на объект обычно число, значение которого совпадает с указателем. Во-вторых, мы не имеем возможности перемещать объекты в куче(а такое перемещение позволяет существенно ускорить выделение памяти). В-третьих, никаких тебе поколений и каких-либо других плюшек полноценного(отделенного от логики приложения) сборщика мусора.
Для реализации этого безобразия на С++, нам потребуется руками составлять карту gc, что скажется на ограничении классов объектов, которые можно будет размещать в такой куче, и/или на производительности кода(т.к. в отличие от jit нам придется строить карту каждый раз, т.к. мемоизация не будет корректной).
Так это не сборка мусора, а обычное ручное управление памятью. Как сейчас в С++ и сделано. Просто в отличие от голого Си, в С++ есть RAII, что упрощает построение такого кода.
Вот вас тут и спрашивают, каким вы видите алгоритм поиска доступных объектов в сборщике для С++.
для тех кто в танке: ЛЮБЫЕ. Хотите как в яве? Ну делайте, в чём проблема-то? Что вам мешает?
Boehm ищет в «памяти»(в стеке каждого потока, в регистрах, в статической памяти, в куче, в собственной куче)
у вас на нём Света с Климом сошлась? Что, если кто-то сделал так, то это доказывает, что иначе — никак?
Во-первых, мы можем принять за ссылку на объект обычно число, значение которого совпадает с указателем. Во-вторых, мы не имеем возможности перемещать объекты в куче(а такое перемещение позволяет существенно ускорить выделение памяти). В-третьих, никаких тебе поколений и каких-либо других плюшек полноценного(отделенного от логики приложения) сборщика мусора.
с моим подходом
1. Не можем. Ибо информация об указателе хранится внутри класса отдельно от указателя.
2. Мы можем перемещать объекты в куче, как нам заблагорассудится. Точнее — сами объекты останутся, но их содержимое будет прыгать куда угодно. Да, при этом счётчики ссылок уже не подходят.
3. Вам доступны любые плюшки, какие вы пожелаете.
Для реализации этого безобразия на С++, нам потребуется руками составлять карту gc, что скажется на ограничении классов объектов, которые можно будет размещать в такой куче, и/или на производительности кода(т.к. в отличие от jit нам придется строить карту каждый раз, т.к. мемоизация не будет корректной).
накладные расходы будут ровно такими же, как и в любой другой реализации GC. Если ты с этим не согласен — обосновывай. Расскажи, как твоя мемоизация происходит у тебя, и почему у тебя не получилось сделать это в C++. Я расскажу, в чём ты ошибаешься, и как это исправить.
для тех кто в танке: ЛЮБЫЕ. Хотите как в яве? Ну делайте, в чём проблема-то? Что вам мешает?
Отсутствие метаинформации о типах объектов, отсутствие карты полей-ссылок объекта.
с моим подходом
Твой подход - это ручное управление памятью.
накладные расходы будут ровно такими же, как и в любой другой реализации GC. Если ты с этим не согласен — обосновывай. Расскажи, как твоя мемоизация происходит у тебя, и почему у тебя не получилось сделать это в C++. Я расскажу, в чём ты ошибаешься, и как это исправить.
Обычная jit'овая мемоизация. В С++ она невозможно для GC, поскольку у тебя будет машкод, а не интерпретируемый байткод. Ты не сможешь корректно запомнить карту для функции(например), т.к. при следующем исполнении данной функции, карта может быть совсем другой и ты не можешь это определить, для этого тебе придется интерпретировать машкод.
Отсутствие метаинформации о типах объектов, отсутствие карты полей-ссылок объекта.
сделай поля с метаинформацией, и сделай карту. Кто тебе запрещает?
Твой подход - это ручное управление памятью.
безусловно. Не боги горшки обжигают. И «само по себе» ничего не происходит. Во всяком случае в CS.
Обычная jit'овая мемоизация. В С++ она невозможно для GC, поскольку у тебя будет машкод, а не интерпретируемый байткод.
1. почему «невозможна»?
2. что мне мешает сделать байткод, если это так уж НАДО?
Ты не сможешь корректно запомнить карту для функции(например), т.к. при следующем исполнении данной функции, карта может быть совсем другой и ты не можешь это определить, для этого тебе придется интерпретировать машкод.
class A
{
// ...
}
class B
{
void set_x(ref A x)
{
m_x = x;
}
ref A get_x()
{
return m_x;
}
private ref A m_x
}
//...
void set_b_x(ref B b1, ref B b2)
{
b1.set_x(b2.get_x);
}
//...
ref B make_my_b()
{
ref A a = new A;
ref B b1 = new B;
ref B b2 = new B;
// ...
b2.set_x(a);
set_b_x(b1, b2);
//...
return b1;
}
сделай поля с метаинформацией, и сделай карту. Кто тебе запрещает?
Я могу это написать для рантайма, но я не могу заставить С++ записывать эту информацию. Мне придется определять и использовать кучу макросов. Я никак в С++ не могу сделать так, чтобы
class A
{
// ...
private:
gc_ref<B> m_x;
};
Формировал для A какую-то метаинформацию. Понимаешь?
безусловно.
Тогда какой смысл называть это сборкой мусора?
И «само по себе» ничего не происходит.
Так при сборке мусора это делает сборщик мусора, отдельный модуль, являющийся частью среды. А у тебя что?