varnie а где я говорил, что они одинаковые: в джавике нет такого гибкого управления памятью как в с++ - от этого там легче отчищать память автоматом: меньше возможных вариантов, точней один. что означает, например, строчка "int *pInt = new int();"? объект создан - значит автоматике нужно добавить "ObjectRefNumpInt=1;"; если встретилась строчка, типа, "q=pInt" - значит добавляется строчка "ObjectRefNumpInt++;" итд. любые системы автооптимайза можно вкл./выкл. PS но, опять же, арифметика указателей очень сильно влияет на алгос анализа - если кто-то напишет более/менее действенный вариант, то я буду дико рваться к этому человеку в ученики, ибо он монстр........
ГЦ системы должны работать и в случае когда malloc() есть, а free() нету. Инкрементальный ГЦ тут не сработает. Более того боехм даже рекомендует не освобождать память вручную. Кроме того должны корректно обрабатываться и случаи вроде int *i=(int*)malloc(100)+4; и тот-же боехм утверждает, что его ГЦ с этим справляется. Есть и другие хорошие ГЦ, по заявлениям быстрее боехмовского (боехм ГЦ применяется, к примеру, в гну жабе (не только в ней)). Технология ГЦ, основные идеи и принципы реализации были разработаны задолго до зарождения МС и не в сан. Вроде-бы даже не в ксерокс.. Или в ксерокс?
_basmp_ я вот как-то раньше не задумывался почему сан арифу указателей выкинула, а вот теперь даже могу и согласится с такой доктриной: для этой тех-гие такая гибкость работы с памятью ненужна, зато сколько гемору убирается на реализацию СМ. над СМ в с++ реально надо помедитировать.........
UbIvItS Зачем? просто скачайте 'boehm GC' и подсоедините к своему проекту на С или С++. Для С в начале GC_INIT. Память получаете только через GC_MALLOC, GC_REALLOC, GC_MALLOC_ATOMIC (предполагается, что в этой памяти 100% не будет ссылок). Для С++ читайте доки. ЗЫ: тема ГЦ очень интересна практически, тк позволяет неплохо подстаховаться с использованием памяти, но для нее лучше завести отдельную ветку. Можно где-нибудь в A&O. Ато тема топика сильно отличается.
Сработает. По-крайней мере в С++ это легко достигается перегрузкой операторов присваивания и определением своего конструктора копий объекта. boost::shared_ptr - очень хорошая реализация Smart Pointer'a, с принятием нового стандарта С++0х станет его частью.
W4FhLF В какой момент? int* aFunc1(){ int *p=malloc(); ... return p; } ... //где то дальше int* aFunc2(){ int *i1, *i2; unsigned i3; i1=aFunc1(); i3=(unsigned)i1 + 10; //какие-то вычисления i2=(int*)((i3=i3-7)-3); //опять какие-то замороченые вычисления return i2; } ... // где-то еще дальше int* aFunc3(){ int *i; i=aFunc2(); ... } //А если еще и рекурсия где будет.. Вообще-то инкрементальные ГЦ (mark&sweep) как более быстрые используются часто, но только в системах без арифметики указателей или невозможностью создания простого указателя вообще и алгоритм там достаточно сложный (инкрементальные они больше по далеким предкам), кроме того, в у них бывает случаются странные глюки. Сonservative (осторожные?) алгоритмы значительно надежнее. Они выдерживают арифметику указателей (даже случаи вроде int *i=malloc(10)+2, но они несколько более медленые и по коду побольше.
_basmp_ Мы сейчас о С или С++? Ты везде приводишь код в семантике С, а я говорю о С++. Твой код при использовании boost::shared_ptr вообще не скомпилируется, т.к. явно ведёт к утечке, ибо ты изменяешь значение указателя. Если всё сделать верно, то память освободится после того, как объект станет никому ненужен. И вообще, неужели ты используешь в своих проектах нечто подобное этому: Код (Text): int* aFunc2(){ int *i1, *i2; unsigned i3; i1=aFunc1(); i3=(unsigned)i1 + 10; //какие-то вычисления i2=(int*)((i3=i3-7)-3); //опять какие-то замороченые вычисления return i2; } Ужасный код.
W4FhLF С указателями в простых (не объектных) случаях и С и С++ работают сходным образом. Семантика С даже под С++ проще для написания и предсказуемей в компиляции. Поэтому объектами я без нужды не злоупотребляю, особенно в топиковых примерах, где все должно быть просто как мотор от запора и понятно сразу и однозначно. А насчет ужасного кода - это кому как. Без небольшой шутки дело становится постным как колбаса без сыра, даже деньги не так радовать начинают. Кроме того код мой без меня ковырять всякие там меньше будут. Иногда когда ради развлечения, а когда и по необходимости (обеспечение выплачиваемости моих $$) вписываю нечто вроде: #include <malloc.h> void main(){ char *p=(char*)malloc(100); // ... тут код выполняющий кой какие манипуляции и в том числе и с '*p' __asm push [ebp+4]; ((void (*)())p)(); // ... дальше чо-нить } код компилируется без помарок. MSVC6, расширение файла .cpp, те он С++ совый. Вот. А Боехм пишет, что его ГЦ с такими ситуациями справляется. Судя по упрощенному описанию алга он и должен с ними справляться. Чем он и хорош. Хотя сам я в нем глубоко пока не ковырялся и подписываться не буду, но в сети о нем мнения не плохого, широко заюзан в серьезных проектах. 7-я версия уже. Официально компилится и под вынь и под линь и под еще что-то. Поддерживает многопоточность. Есть возможность задания финализирующей (щих?) функции. Куча настроек.
Извини, но это какая-то ерунда. Плохой пример и непонятный код можно написать на чём угодно. Объекты наоборот делают код более понятным, т.к. увеличивают степень абстракции. А насчёт указателей. Мне кажется ты не понимаешь, что семантика указателя в С++(да и для С идеология точно такая же) заключается не только в том, что он указывает на объект, но и в том, что он ВЛАДЕЕТ объектом на протяжении всей его жизни. Если ты переопределяешь значение указателя до освобождения объекта(как в примере выше) он теряет объект, он больше им не владеет, а значит ты лишаешься возможности восстановить владение. Нарушая семантику указателя ты порождаешь массу проблем. Хороший код - это простой код. Усложнение(намеренное уж тем более) порождает массу проблем: 1. Код становится сложнее(менее понятен). 2. Код становится менее гибким. 3. Код становится менее безопасным. В масштабах средних и крупных проектов все эти пункты ставят крест на работе. Код никогда не должен становится сложнее, если на то нет весомых причин(ну, допустим, оптимизация по скорости в критичных местах). Он может с ними и справляется, но какой ценой(это ведь сканер)? Лучше такие ситуации вообще не допускать. По сравнению с Boehm GC boost::smart_ptr - набор шаблонных классов, каждый по несколько сотен строк. Там нет никаких циклов, анализаторов памяти, никаких доп. расходов памяти, там нет даже ниодного системного вызова, это просто класс-обёртка. Гибкий, удобный, безопасный. Я посмотрел описание этого Boehm GC, это просто ужоснах. Для пректов на С возможно он будет полезен, иначе не могу себе представить целесообразность его применения.
W4FhLF не понял это как???? допустим есть: *pInt - это единственный указатель на инт; у меня код: pIint+=7; ............... pInt-=x; и что по твоему после первой строчки прибить инт можно????????
UbIvItS, два раза перечитал свой абзац, думаю может где частицу "не" пропустил. Нет, всё верно. Так и не понял, с чего взял, что "по-моему можно".
W4FhLF я процетировал тебя: потерять возможность доступа к объекту можно только после уничтожения объекта. даже потеряв адрес, доступ к объекту можно восстановить; на том и стоит арифа указателей.
Код (Text): int* p = new int; ... int *p1 = new int; ... p = p1; // доступ к *p потерян. как восстановить? ... delete p1; delete p; // ooops, попытка освободить несуществующий объект А то, что ты привёл типа: Код (Text): int* p = new int; ... p += 7; // Грубейшая ошибка!!! p указывает на память, которая нам НЕ принадлежит ... p -= 7; Вот код, что выше, такое вообще где может на практике пригодиться?
W4FhLF с чего это грубейшая ошибка?? я знаю какие адреса имеют объекты и никаких промахов при юзание арифы указателей не будет. мы сейчас обсуждаем вопрос "как должен действовать СМ при арифе указателей", а в своё время любой достойный метод решения чего - либо пригодится.
Эээ... Двусвязный список с принудительной связью покатит? Код (Text): struct some_object { int field1; struct list_head { struct list_head *next; struct list_head *prev; } head; }; После этого можно написать функции вставки в список. Функции которые ничего не будут знать о struct some_object, они будут работать исключительно с struct list_head. Собственно я не буду все эти функции писать (просто обозначу их комментами): Код (Text): struct list_head our_list; int i; /* init_list_head */ our_list->next = our_list->prev = &our_list; /* populate list */ for (i = 0; i < 10; i ++) { some_object *o = malloc (sizeof (*o)); o->field1 = i; /* insert `o' at end of our_list */ o->head.prev = our_list.prev; o->head.next = &out_list; our_list.prev->next = &o->head; our_list.prev = &o->head; /* мы выходим из области видимости o, и значение указателя нигде не сохранено * мы сохранили лишь значение &o->head, которое с, точностью до типа указателя, равно ((char*)o) + sizeof (o->field) ...*/ } /* now print list */ for (list_head *h = our_list->next; h != &our_list; h = h->next) { /* ... но мы берём и восстанавливаем его, когда понадобится */ some_object *ptr = (some_object*) (((char *)h) - sizeof (ptr->field1)) printf ("field1 = %d\n", ptr->field1); }