Почему “невозможно” реализовать сборку "мусора" в C из-за слабого контроля типов?

Использовать 1 a float и float division

public static void main(String d[]){
    double g=1f/3;
    System.out.printf("%.2f",g);
}
21
задан Norman Ramsey 11 January 2009 в 01:06
поделиться

7 ответов

Он, вероятно, упомянул то, что можно бросить указатель на интервал и назад на исходный тип указателя. Для GC в значительной степени невозможно вымыться правильно, когда Вы делаете это, рассмотрите:

char * p = (char *) malloc(16);
int i = (int) p;
p = 0;
// GC runs and finds that the memory is no longer referenced
p = (char *) i;
// p is now a dangling pointer

РЕДАКТИРОВАНИЕ : Вышеупомянутое только произведет висячий указатель с точным GC. Как другие указали, консервативный коллектор может все еще правильно обработать этот сценарий, как это предполагает, что любой комбинация двоичных разрядов, которая могла быть допустимым указателем на самом деле, является указателем и таким образом не освободит выделенную память. Однако это больше не, конечно, возможно, когда я далее изменяюсь таким образом, что это больше не похоже на допустимый указатель на коллектор, например, следующим образом:

char * p = (char *) malloc(16);
int i = ~((int) p);
p = 0;
// GC runs and finds that the memory is no longer referenced
p = (char *) ~i;
// p is now a dangling pointer

, Кроме того, (снова, поскольку другие указали) только невозможно реализовать GC для C, если Вы хотите сохранить полную функциональность языка. Если Вы воздерживаетесь от использования приемов как вышеупомянутое (т.е. Вы ограничиваетесь подмножеством возможных операций), тогда, GC действительно выполним.

24
ответ дан 29 November 2019 в 20:03
поделиться

Совершенно возможно реализовать безотносительно диспетчера памяти можно думать в C. Выгода - то, что тогда необходимо использовать ее функции выделения/освобождения исключительно и ограничить 'волшебство указателя' вещами, которые оно может отслеживать. Aditionally, управление памятью могло бы быть ограничено определенными поддерживаемыми типами.

, Например, Objective C сохраняет/выпускает систему и автовыпускает пулы, в основном диспетчеры памяти, реализованные в C. Многие библиотеки также реализуют свою собственную, простую форму управления памятью как подсчет ссылок.

Затем существует сборщик "мусора" Boehm. Для использования его просто замените Ваш malloc() / realloc() вызовы с версиями Boehm, и Вы никогда не должны звонить free() снова. Считайте [приблизительно 113] возможные проблемы с этим подходом .

кроме того, проверка эта страница Википедии для быстрого обзора того, как работают консервативные сборщики "мусора".

12
ответ дан Christoph 29 November 2019 в 20:03
поделиться

Если Вы читаете правильные газеты, и у Вас есть степень бакалавра в области CS, на самом деле довольно легко реализовать достойное консерватор сборщик "мусора" для C---, у меня есть дюжина студентов, которые сделали его как осуществление класса, занимающее приблизительно четыре недели. Тогда проведите 20 лет, улучшая его, и Вы добираетесь коллектор Boehm (libgc) .

основная идея проста: если существует немного шаблона где-нибудь в регистре, на стеке, в глобальной переменной, или в живом объекте "кучи", и что комбинация двоичных разрядов, оказывается, адрес, который падает в объекте, выделенном с malloc, чем тот объект считают живым . Любой объект, который не жив, не может возможно быть достигнут следующими указателями, и таким образом, он может исправляться и использоваться для удовлетворения будущих запросов выделения. Эта техника воздействует на аппаратное представление указателей, и это полностью независимо от , тип указателя---типы не важен здесь.

Это верно, что существует протест: консервативные методы сборки "мусора" можно дурачить путем преднамеренного сокрытия указателей. Сожмите содержащие указатель структуры, сохраните единственную копию указателя на диске, запутайте указатель XORing 0xdeadbeef, и все эти методы повредят консервативный коллектор. Но этот вид проблемы чрезвычайно редок, если не сделано сознательно. Авторы оптимизирующих компиляторов обычно боятся скрывать указатели от такого коллектора.

самая интересная часть Вашего вопроса , почему делают это . Три причины:

  • Это устраняет возможность многих ошибок памяти-manangement.

  • Это упрощает Ваши API , потому что больше не необходимо определить, кто выделяет память, кто владеет выделенной памятью, необходимо ли скопировать память, и кто ответственен за освобождение памяти.

  • , Хотите верьте, хотите нет, это может быть быстрее , чем использование malloc и free.

6
ответ дан Norman Ramsey 29 November 2019 в 20:03
поделиться

Это не невозможно для реализации сборщика "мусора" для C (и на самом деле, они действительно существуют как простое , поиск Google показывает), это просто трудно, потому что может быть трудно определить, ли определенная строка битов указатель в выделенный блок или всего взгляды как один.

причина это - проблема, то, потому что C (и C++, в этом отношении) позволяет Вам бросать от типа указателя до целочисленного типа, таким образом, целочисленная переменная могла бы содержать адрес в выделенном блоке, препятствуя тому, чтобы GC освободил тот блок, даже при том, что то значение не было предназначено, чтобы быть указателем.

, Например, скажем, у меня есть блок выделенной памяти. Давайте предположим, что этот блок памяти выделяется, начиная в адресе 0x00100000 (1,048,576) и 1 МБ длиной, поэтому расширяется на 0x001FFFFF (2,097,151).

Скажем, я также храню размер файла изображения в переменной (давайте назовем его размером файла). Этот файл изображения, оказывается, составляет 1,5 МБ (1 572 864 байта).

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

int fileSize;
{
    char *mem = (char*)malloc(1048576);
    fileSize = (int)(mem + 524288);
}
// say GC runs here

или если я только что сделал это:

int fileSize;
{
    char *mem = (char*)malloc(1048576);
    fileSize = 1572864;
}
// say GC runs here;

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

, Но сборщики "мусора" для C (и C++) делают , существуют. Ценны ли они, вопрос для различного обсуждения.

3
ответ дан P Daddy 29 November 2019 в 20:03
поделиться

Проблема состоит в том, что нет никакого пути ко времени выполнения для знания наверняка, если на какую-либо часть памяти ссылаются или нет. Даже если Вы обертываете все выделение памяти в код, который регистрирует использование, можно все еще получить указатели на используемую память через управление регулярным указателем (или по ошибке). Броски только делают проблему тяжелее для времени выполнения. Таким образом, если время выполнения освободит часть памяти, оно испортит вещи для любых указателей, все еще указывающих на ту область памяти. Очевидно, ситуация только ухудшается, когда Вы полагаете, что сборка "мусора" должна работать на многопоточные приложения также.

3
ответ дан Brian Rasmussen 29 November 2019 в 20:03
поделиться

Невозможно реализовать точный , сборщик "мусора" для C из-за свобод предоставил указатели C и то, что длина массива C является чьим-либо предположением. Это означает, что много сложных подходов сборки "мусора" не может использоваться. (Копирование и уплотнение сборщиков "мусора" приходят на ум.)

, однако, возможно реализовать консервативный сборщик "мусора" ( boehm), который в основном принимает все, что похоже на него, мог бы быть указатель, указатель. Это не очень эффективно, но это работает на соответственно снисходительное определение "работ".

2
ответ дан bendin 29 November 2019 в 20:03
поделиться

C не со слабым контролем типов, но этот код иллюстрирует трудность при встраивании сборщика "мусора" на язык:

#include <stdio.h>
#include <stdlib.h>

int GetSomeMemory() {
    char* pointerToHeapMemory = malloc(10);
    return (int)pointerToHeapMemory;
}

int main() {
    int memoryAddress = GetSomeMemory();

    /* at this point a garbage collector might decide to clear up the memory that
     * was allocated in GetSomeMemory on the grounds that pointerToHeapMemory 
     * is no longer in scope. But the truth is we still know about that memory and 
     * we're about to use it again... */

    char* anotherPointerToHeapMemory = (char*) memoryAddress;

    sprintf(anotherPointerToHeapMemory, "123456789\0");
    printf("%s\n", anotherPointerToHeapMemory);
}

Сборка "мусора" может быть сделана, пока все работающие над проектом соглашаются избежать такого рода вещи и использовать единый набор функций для выделения и доступа к памяти. Например, это - реализация сборщика "мусора" C

0
ответ дан d4nt 29 November 2019 в 20:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: