Главное меню
Мы солидарны с Украиной. Узнайте здесь, как можно поддержать Украину.

Глобальные переменные

Автор RawonaM, марта 1, 2011, 15:07

0 Пользователи и 1 гость просматривают эту тему.

RawonaM

Столкнулся с такой манифестацией глобальнопеременнофобии:

Для выполенния одного задания на С я написал некий простенький garbage collector. Есть функции safe_malloc/safe_realloc/safe_free, пользуясь которыми мне не обязательно освобождать память, они все помнят и сами освобождают неосвобожденное. Указатель на массив указателей на выданные блоки памяти я храню в глобальной переменной как и счетчик оных.

Получил назад свое задание, сняли 3 балла за использование глобальных переменных. Считаю, что это несправедливо, потому что не вижу никакого рационального способа убрать их и не устраивать каких-то сложных и непонятных трюков. Есть случаи, когда глобальные переменные оправданы, то зачем за это снимать? :-\

Что вы думаете? Какое решение без глобалов вы можете предложить?

Python

Вместо глобальных переменных лучше использовать статические.
Пролетареві ніколи вчити європейських мов, бодай би свою знати добре і на ній принести до своєї хати світло знання (Гнат Хоткевич)
ÆC CASALI NAXI PRASQURI: AHOV CÆRU, MERTVÆRI TÆ SLAVUTÆT!
Вони просили його: «Скажи: кетум», а він говорив: «сатем», і не міг вимовити правильно.
Хотелось бы также отметить, что "Питон" - это "мышиный язык" : "пи+тон". © АБР-2

RawonaM

Цитата: Python от марта  1, 2011, 15:11
Вместо глобальных переменных лучше использовать статические.
Логично. Но если нужно общую между двумя-тремя функциями, то как?

Python

Переменная объявляется как static, но не внутри функции, а за ее пределами. Она будет доступной для всех функций в этом модуле и недоступной для других модулей.
Пролетареві ніколи вчити європейських мов, бодай би свою знати добре і на ній принести до своєї хати світло знання (Гнат Хоткевич)
ÆC CASALI NAXI PRASQURI: AHOV CÆRU, MERTVÆRI TÆ SLAVUTÆT!
Вони просили його: «Скажи: кетум», а він говорив: «сатем», і не міг вимовити правильно.
Хотелось бы также отметить, что "Питон" - это "мышиный язык" : "пи+тон". © АБР-2

myst

Цитата: RawonaM от марта  1, 2011, 15:07
Что вы думаете? Какое решение без глобалов вы можете предложить?
Ты ничего не забыл показать? :eat:

RawonaM

Цитата: Python от марта  1, 2011, 15:25
Переменная объявляется как static, но не внутри функции, а за ее пределами. Она будет доступной для всех функций в этом модуле и недоступной для других модулей.
Ну так это же и есть глобальная, только для этого модуля и у нее те же недостатки как и у "нестатических" глобальных. Не уверен, что к глобальным "статическим" отнеслись бы по-другому.

В общем-то да, вы правы, что так было бы лучше их определить, но функционально ничего это не меняет.

RawonaM

Цитата: myst от марта  1, 2011, 15:32
ЦитироватьЧто вы думаете? Какое решение без глобалов вы можете предложить?
Ты ничего не забыл показать? :eat:
Например?


RawonaM


myst

Цитата: RawonaM от марта  1, 2011, 15:35
Ну так это же и есть глобальная, только для этого модуля и у нее те же недостатки как и у "нестатических" глобальных. Не уверен, что к глобальным "статическим" отнеслись бы по-другому.
Если суть претензии была в необоснованно широкой области видимости, а локальная переменная не годится, то всё правильно Python советует. Других вариантов в Си нет.

Python

Цитата: RawonaM от марта  1, 2011, 15:35
но функционально ничего это не меняет.
Меняет, если имя переменной каким-то образом совпало с другим идентификатором в библиотеках или в другом модуле. Кроме того, глобальная переменная считается дыркой в безопасности: при желании, можно написать другой модуль, изменяющий эту глобальную переменную или читающий ее данные, и, например, внедрить его в библиотеку, с которой этот модуль линкуется.
Цитата: RawonaM от марта  1, 2011, 15:35
Не уверен, что к глобальным "статическим" отнеслись бы по-другому.
А я уверен. Объективно есть ситуации, когда переменная должна использоваться несколькими функциями, но делать ее глобальной и доступной для всех модулей — плохой стиль. Глобальной следует делать переменную, если она рассчитана на непосредственный доступ и изменение из других модулей, иначе она должна быть (общей) статической.
Пролетареві ніколи вчити європейських мов, бодай би свою знати добре і на ній принести до своєї хати світло знання (Гнат Хоткевич)
ÆC CASALI NAXI PRASQURI: AHOV CÆRU, MERTVÆRI TÆ SLAVUTÆT!
Вони просили його: «Скажи: кетум», а він говорив: «сатем», і не міг вимовити правильно.
Хотелось бы также отметить, что "Питон" - это "мышиный язык" : "пи+тон". © АБР-2

myst

Цитата: RawonaM от марта  1, 2011, 16:07
А зачем? Я вроде всю ситуацию ясно объяснил.
Хотя бы затем, чтобы решить, насколько они правы, и посоветовать что-то конкретное. На сферических конях ведь далеко не уедешь. :donno:

RawonaM

Цитата: myst от марта  1, 2011, 16:08
Если суть претензии была в необоснованно широкой области видимости, а локальная переменная не годится, то всё правильно Python советует. Других вариантов в Си нет.
Так я с Pythonoм согласен. Но мне кажется что претензии на этом не ограничиваются, мне кажется действует тотальный запрет на глобальные (т.е. вне функций).

myst

Цитата: Python от марта  1, 2011, 16:10
Кроме того, глобальная переменная считается дыркой в безопасности: при желании, можно написать другой модуль, изменяющий эту глобальную переменную или читающий ее данные, и, например, внедрить его в библиотеку, с которой этот модуль линкуется.
:D Жесть. Всё-таки экстравагантных фантазий нашему Python'у не занимать.

myst

Цитата: RawonaM от марта  1, 2011, 16:13
Так я с Pythonoм согласен. Но мне кажется что претензии на этом не ограничиваются, мне кажется действует тотальный запрет на глобальные (т.е. вне функций).
Если бы это были плюсы, я бы ещё понял. В си и так слишком мало средств, чтобы ещё какие-то тотальные запреты вводить. Другое дело, что возможно существует решение без глобальных переменных, которое ты не нашел.

RawonaM

Цитата: Python от марта  1, 2011, 16:10
Цитироватьно функционально ничего это не меняет.
Меняет, если имя переменной каким-то образом совпало с другим идентификатором в библиотеках или в другом модуле.
А что, если я в другом модуле определю такой же индентификатор, то они будут конфликтовать? По-моему пока нет декларации extern в других модулях, они не видят эту переменную.

RawonaM

Цитата: myst от марта  1, 2011, 16:14
ЦитироватьКроме того, глобальная переменная считается дыркой в безопасности: при желании, можно написать другой модуль, изменяющий эту глобальную переменную или читающий ее данные, и, например, внедрить его в библиотеку, с которой этот модуль линкуется.
:D Жесть. Всё-таки экстравагантных фантазий нашему Python'у не занимать.
Но он же правильно говорит.

RawonaM

Значит выходит, что я неправильно понял, что не понравилось проверяющему?..
Блин, у меня нет с ним прямой связи, это напрягает. И вообще семестр уже закончился и теперь хрен кого найдешь.

RawonaM

Цитата: myst от марта  1, 2011, 16:17
ЦитироватьТак я с Pythonoм согласен. Но мне кажется что претензии на этом не ограничиваются, мне кажется действует тотальный запрет на глобальные (т.е. вне функций).
Если бы это были плюсы, я бы ещё понял. В си и так слишком мало средств, чтобы ещё какие-то тотальные запреты вводить. Другое дело, что возможно существует решение без глобальных переменных, которое ты не нашел.
Не знаю, чем тебе поможет код...

Ну вот:
/* dynamic array of pointers to allocated buffers */
void **alloc_ptrs = NULL;
/* counter of allocated buffers */
int alloc_cnt = 0;

/*
* Allocates memory, storing a pointer for later automatic freeing in case of
* exiting on error.
*/
void *safe_malloc(size_t size)
{
    void *new_buffer, *tmp;

    /* resize pointer array and allocate the buffer */
    tmp = realloc(alloc_ptrs, sizeof(void*)*(alloc_cnt+1));
    if (tmp == NULL || NULL == (new_buffer = malloc(size)))
        safe_exit(ALLOC_ERROR);

    /* update pointers array and counter*/
    alloc_ptrs = tmp;
    alloc_cnt++;
    alloc_ptrs[alloc_cnt-1] = new_buffer;

    return new_buffer;
}

/*
* Resizes the buffer that ptr was previously allocated with safe_malloc.
* If ptr is NULL, the function is identical to safe_malloc.
*/
void *safe_realloc(void *ptr, size_t size)
{
    int i;

    /* allocating new buffer */
    if (ptr == NULL)
        return safe_malloc(size);

    /* freeing a buffer */
    if (size == 0)
    {
        safe_free(ptr);
        return NULL;
    }

    /* reallocate and update the pointer in array */
    for (i = 0; i < alloc_cnt; i++)
        if (alloc_ptrs[i] == ptr)
        {
            if ((ptr = realloc(ptr, size)) == NULL)
                safe_exit(ALLOC_ERROR);

            alloc_ptrs[i] = ptr;
            return alloc_ptrs[i];
        }

    /* if we get here, this pointer was not previously allocated */
    return NULL;
}

myst

Цитата: RawonaM от марта  1, 2011, 16:18
Но он же правильно говорит.
Сейчас я тебе открою тайну, но только никому, хорошо? :tss:
Если у тебя есть доступ к исходникам или объектникам, ты можешь любую переменную сделать глобальной при желании. Смекаешь? :)

RawonaM

Цитата: myst от марта  1, 2011, 16:27
ЦитироватьНо он же правильно говорит.
Сейчас я тебе открою тайну, но только никому, хорошо? :tss:
Если у тебя есть доступ к исходникам или объектникам, ты можешь любую переменную сделать глобальной при желании. Смекаешь? :)
Если у тебя есть только обж и гедер — что ты можешь сделать? Даже если ты формат обжа знаешь, то у другого компилятора он может быть другим.
Мы же говорим о теории программирования, а не о том, как похакать можно.


RawonaM

Ну что, весь код прямо что ли закопипастить? Я релевантные куски :)
Принцип ясен. Там где автоосвобождение, оно тоже эту же глобалку читает.

myst

Цитата: RawonaM от марта  1, 2011, 16:32
Если у тебя есть только обж и гедер — что ты можешь сделать? Даже если ты формат обжа знаешь, то у другого компилятора он может быть другим.
Мы же говорим о теории программирования, а не о том, как похакать можно.
При чём тут теория, если речь о конкретных вещах?
На уровне сишных объектников нет никакой защиты, она там просто не нужна. Поэтому фантазии о дырках в защите на этом уровне очень юмористичны.

myst

Цитата: RawonaM от марта  1, 2011, 16:36
Ну что, весь код прямо что ли закопипастить? Я релевантные куски :)
Принцип ясен. Там где автоосвобождение, оно тоже эту же глобалку читает.
Не, ну ты можешь на пальцах объяснить логику. :)

Быстрый ответ

Обратите внимание: данное сообщение не будет отображаться, пока модератор не одобрит его.

Имя:
Имейл:
Проверка:
Оставьте это поле пустым:
Наберите символы, которые изображены на картинке
Прослушать / Запросить другое изображение

Наберите символы, которые изображены на картинке:

√36:
ALT+S — отправить
ALT+P — предварительный просмотр