LINUX.ORG.RU

C++ + ARC


0

3

Есть ли какая-нибудь возможность сделать automated reference counting или GC для C++ так, чтобы не приходилось писать освобождения памяти руками? Примерно так, как это работает в Objective C под маком. Даже если для этого понадобится перейти на Шланг - да плевать, оно того стоит.

имеются в виду не специфичные для С++-паттерны работы с памятью, а именно полностью автоматическая генерация соответствующего кода.

со времен 1983-его года прошло 30 лет, наверняка кто-то работал над этим..

(причины стандартные - раздражает невозможность писать вызовы типа f(g(x)) для генерации и манипуляции интересными сложными структурами данных, что приводит к низкому уровню абстракции; постоянное выискивание мест где что-то там потерялось или могло бы потеряться; поиск и организация точек выхода из функций... это отнимает излишне много времени, если не сказать «всё время»)

★★★★☆

Ответ на: комментарий от BlackHawk

если с «std::shared_ptr в С++11» все так чудесно, почему бы в компиляторе на этапе разбора AST не перехватить все ссылочные рефы, и не заменить их на shared_ptr? Чтобы можно было бы пользоваться базовым языком вообще без размышлений о памяти. Пишешь сцылку, а она там когда-нибудь превратится в shared_ptr, или не превратится, тебе как пользователю языка все равно.

(если что, я абсолютный чайник и не представляю как это работает «на самом деле», так что возможно вопрос не имеет ответа по причине своей глупости, тогда извини)

stevejobs ★★★★☆
() автор топика

А что ты не запилишь простенький autorelease pool? Он решает огромный спектр. Сдался тебе этот ARC, я на SO периодически вижу «памагите ето атладить» без вменямеых ответов — отлаживать невидимую автоматику и правда тяжело.

arturpub ★★
()
Ответ на: комментарий от arturpub

А что тебе мешает писать вызовы типа f(g(x))?

Некому освободить результат g.

ЯННП

void* g(size_t n) {
    return malloc(n);
}

void f(void *p) {
    if(p) free(p);
}

int main() {
    f(g(100500));
}
DELIRIUM ☆☆☆☆☆
()
Ответ на: комментарий от DELIRIUM

Получается f и g связаны политикой освобождения памяти. Что если не хочется освобождать параметр, переданный в f?

arturpub ★★
()
Ответ на: комментарий от DELIRIUM

Для примера можно рассмотреть printf(asprintf(«%%.%ud», precision), value).

arturpub ★★
()

Ещё у Джеффа Элджера, в его «C++ for real programmers» есть глава про сборку мусора. Тоже можно почитать, проникнуться, и всё такое.

one_more_hokum ★★★
()

Чтобы сделать automatic reference counting нужно, чтобы для начала был этот самый reference counting.

Кстати говоря, порт Cocos2d для C++ - Cocos2dx имеет такую же модель управления памятью как и OjbC с reference counting и autorelease pool.

mono ★★★★★
()

Objective C++ не поможет? Шланг вроде портирован везде.

Вообще подтверждаю. Самая удобная и правильная модель управления памятью. Странно, что GC сейчас везде используется, (a)rc мне больше нравится.

Legioner ★★★★★
()
Ответ на: комментарий от Legioner

rc не может же разруливать циклические ссылки, а gc может. (хотя при желании можно и на rc избежать цикл. ссылок и все будет ок)

TakeOver
()

есть такая вещь как boehm gc(как-то так) - консервативный gc для с/с++, емнип, там можно даже зарегистрировать финализатор для объекта, что бы сборщик его вызвал перед удалением. И этим gc когда-то пользовались в mono и в какой-то швободной реализации jvm. Но сам не пользовался.

TakeOver
()
Ответ на: комментарий от TakeOver

rc не может же разруливать циклические ссылки, а gc может. (хотя при желании можно и на rc избежать цикл. ссылок и все будет ок)

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

Legioner ★★★★★
()
Ответ на: комментарий от Legioner

Самая удобная и правильная модель управления памятью

А ничего, что на каждое копирование указателя добавляются атомарные инкремент и декремент счётчика?

Begemoth ★★★★★
()

раздражает невозможность писать вызовы типа f(g(x)) для генерации и манипуляции интересными сложными структурами данных, что приводит к низкому уровню абстракции;

Да можно так писать, вполне. Главное - уметь :)

yoghurt ★★★★★
()
Ответ на: комментарий от Begemoth

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

Если прям сильно нужно оптимизировать какое-то конкретное место, никто не запрещает. Но по умолчанию это экономия даже не на спичках.

Legioner ★★★★★
()
Ответ на: комментарий от Legioner

А значит он будет в кешах и операции со счетчиком будут практически бесплатные.

В кеше какого ядра какого процессора?

Begemoth ★★★★★
()
Ответ на: комментарий от stevejobs

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

Как пользователь языка можешь и сам писать shared_ptr.

invy ★★★★★
()
Ответ на: комментарий от stevejobs

если с «std::shared_ptr в С++11» все так чудесно, почему бы в компиляторе на этапе разбора AST не перехватить все ссылочные рефы, и не заменить их на shared_ptr?

  1. И забить на совместимость с С++98?
  2. А если требуется не совместное владение (std::shared_ptr), а одиночное (std::unique_ptr)?
  3. Не соответствует идеологии С++ - ты платишь только за то, что используешь.

Чтобы можно было бы пользоваться базовым языком вообще без размышлений о памяти.

В языках с GC тоже надо думать о памяти.

Begemoth ★★★★★
()
Последнее исправление: Begemoth (всего исправлений: 1)
Ответ на: комментарий от Begemoth

В кеше какого ядра какого процессора?

Очевидно - того, который выполняет операции со счетчиком и во всех вышестоящих кешах.

Legioner ★★★★★
()
Ответ на: комментарий от stevejobs

Чтобы можно было бы пользоваться базовым языком вообще без размышлений о памяти

потому, что базовый язык это new/delete, а shared_ptr это стандартная библиотека. точно такой же вопрос можно задать про джаббу: почему там нету коллекций в виде конструкций языка?

x0r ★★★★★
()
Ответ на: комментарий от invy

С начала 90х напридумывали кучу разных способов упростить работу программиста, но ни одна технология (включая ООП), имхо, не дает такого огромного буста к производительности программиста, как автоматическое управление памятью. У эрлангистов нету никакого жава-стайл ООП, нету нормального IDE, но они как-то умудряются писать не сильно медленней. Неважно какое оно там будет, хоть GC, хоть ARC, хоть чорт в ступе, лишь бы автоматическое. Ручное написание поинтеров - это НЕ автоматическое управление памятью.

Допустим, мы наступим себе на яйца, забиндим слово «shared_ptr» на кнопку TAB будем его везде фигачить. Тогда это слово будет повторяться чаще, чем скобочки в лиспе.

Программа будет выглядеть так:

Ехал shared_ptr через shared_ptr
Видит shared_ptr — shared_ptr в shared_ptr
Сунул shared_ptr shared_ptr в shared_ptr
shared_ptr shared_ptr shared_ptr

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

stevejobs ★★★★☆
() автор топика
Последнее исправление: stevejobs (всего исправлений: 1)
Ответ на: комментарий от stevejobs

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

invy ★★★★★
()
Ответ на: комментарий от stevejobs

shared_ptr медленный. Даже немного медленнее ARC в Obj-C, судя по наивным тестам. Во всяких узких местах могут понадобиться ручные указатели.

Можно сделать код немного красивее, написав макроcы. Ref<C> v(new V());

note173 ★★★★★
()
Ответ на: комментарий от stevejobs

Причем вся эта срань абсолютно не требует никакого участия мозга.

Вообще-то требует. Или на выходе тоже срань получится.

DarkEld3r ★★★★★
()
Ответ на: комментарий от arturpub

При условии, что g возвращает указатель на новую память, которой больше никто не владеет, что вообще не очень принято делать. Но если всё же жизнь сложилась так, можно сделать f( std::shared_ptr( g() ) ).

KblCb ★★★★★
()
Ответ на: комментарий от KblCb

Возвращаемые объекты чаще не нужны, чем нужны. Проще вернуть [[[NSString alloc] init] autorelease], или [NSString string], и пусть кому нужно сделает retain, чем «ехал shared_ptr через shared_ptr».

arturpub ★★
()

valgrind + конструктор копирования + стек спасут тебя и твое время

vasily_pupkin ★★★★★
()

Есть ли какая-нибудь возможность сделать automated reference counting или GC для C++ так, чтобы не приходилось писать освобождения памяти руками?

Есть шланг такое умеет. н-р в Хкоде при создании С++ проекта можно указать юзать ли арку для с++.
А вообще RAII ну или куча из без этого смартов

Boy_from_Jungle ★★★★
()
Ответ на: комментарий от invy

зачем вооще руками лезть в указатели, если есть move semantics?

оно должно быть noexcept если ты хочешь его юзать, иначе можешь отгребсти по полной!!

Boy_from_Jungle ★★★★
()
Ответ на: комментарий от arturpub

Проще вернуть [[[NSString alloc] init] autorelease], или [NSString string]

ну или @""; -)

чем «ехал shared_ptr через shared_ptr».

этот смарт с такими объектами лучше не юзать

Boy_from_Jungle ★★★★
()
Последнее исправление: Boy_from_Jungle (всего исправлений: 1)
Ответ на: комментарий от note173

shared_ptr медленный. Даже немного медленнее ARC в Obj-C, судя по наивным тестам.

Конечно, почему люди думают что арка это какой-то чудо-смарт?
Это всего лишь работа компилятора по растановке вместо вас alloc, init, new, autorelease, copy, release, etc. Как я понимаю он все не ложит в autorelease-pool, соответвенно если между new и release будет exception то память уплывет все равно

Boy_from_Jungle ★★★★
()
Последнее исправление: Boy_from_Jungle (всего исправлений: 1)
Ответ на: комментарий от note173

shared_ptr медленный.

потому надо счетчик выносить в сами объекты, и тогда «умные указатели» к ним будут по размеру такие же как «ручные», а по скорости - практически такие же

wota ★★
()
Ответ на: комментарий от Boy_from_Jungle

У них в доках написано, что исключение это shit happens и кроме как presentError: и terminate: ничего дальше не стоит делать. В принципе это оригинальный смысл исключения, какой балбес их придумал юзать для нормального flow control — непонятно.

arturpub ★★
()
Ответ на: комментарий от arturpub

и кроме как presentError: и terminate: ничего дальше не стоит делать.

Не согласен)

Boy_from_Jungle ★★★★
()
Ответ на: комментарий от invy

Да, ну это же и не джава, где на каждый чих по 100500 исключений.

Я не за это. Если вы хотите юзать всю мощь мув-семантики, то нужно придерживаться некоторых правил.
Посмотрите, если вы создаете свой объект и у него есть конструкторы, операторы, функции которые принимают Р-ссылки, то они должны быть noexcept, и если в них произойдет исключение то вы получите сразу terminate. Так что следить нужно в оба, а воообще лучше юзать std::move_if_noexcept, ИМХО.

Boy_from_Jungle ★★★★
()
Ответ на: комментарий от Boy_from_Jungle

Но счетчик в Obj-C точно так же атомарный, и его обновление — не бесплатная операция.

Нет, autorelease pool ARC как раз старается по возможности избегать. Там даже есть специальная рантайм-функция _objc_retainautoreleasedreturnvalue.

note173 ★★★★★
()
Ответ на: комментарий от note173

Но счетчик в Obj-C точно так же атомарный, и его обновление — не бесплатная операция.

В айос ? С чего вдруг? Есть пруф, ибо насколько я помню это обычная uint32

Нет, autorelease pool ARC как раз старается по возможности избегать. Там даже есть специальная рантайм-функция _objc_retainautoreleasedreturnvalue.

Возможно, но раньше у них в доках по айос было написано, что юзайте autorelease

Boy_from_Jungle ★★★★
()
Ответ на: комментарий от Boy_from_Jungle

Есть пруф, ибо насколько я помню это обычная uint32

http://opensource.apple.com/source/objc4/objc4-493.11/runtime/objc-arr.mm
_objc_rootRetain

http://opensource.apple.com/source/CF/CF-744.18/CFRuntime.c
static CFTypeRef _CFRetain

раньше у них в доках по айос было написано, что юзайте autorelease

С появления ARC написано, что переходите на ARC и не думайте про autorelease.

note173 ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.