c - реализация unsetenv(), нужно ли освобождать память?

Как требовалось TLPI exercise 6-3, я реализовал setenv() и unsetenv(), используя putenv(), getenv() и напрямую изменив переменную environ.

Код:

// setenv() / unsetenv() impl
// TLPI exercise 6-3

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>

#define ENV_SEP '='
extern char **environ;

// setenv() impl using putenv() & getenv()
int setenv_impl(const char * name , const char * value , int overwrite ) {
    if(!overwrite && getenv(name)) { // exists & don't overwrite
        return 0;
    } else {
        // construct the new variable
        char *env_var = malloc(strlen(name) + strlen(value) + 2);
        strcpy(env_var, name);
        env_var[strlen(name)] = ENV_SEP;
        strcpy(env_var+(strlen(name)+1), value);

        int result = putenv(env_var);
        if(result==0) {
            return 0;
        } else {
            errno = result;
            return -1;
        }
    }
}

// unsetenv() impl via modifing environ directly,
int unsetenv_impl(const char * name ) {
    char **ep, **sp;
    size_t len;

    len = strlen(name);
    for(ep = environ; *ep != NULL;) {
        if(strncmp(*ep, name, len)==0 && (*ep)[len] == ENV_SEP) {
            // shift all successive elements back 1 step,
            for(sp=ep; *sp != NULL; sp++) {
                *sp = *(sp+1);
            }
        } else {
            ep++;
        }
    }

    return 0;
}

// setenv_impl() test
int setenv_impl_test() {
    char *key = "name";

    setenv_impl(key,"Eric", 1);
    printf("%s\n", getenv(key));

    setenv_impl(key,"Eric2", 0);
    printf("%s\n", getenv(key));

    setenv_impl(key,"Eric3", 1);
    printf("%s\n", getenv(key));

    return 0;
}

// unsetenv_impl() test
int unsetenv_impl_test() {
    char *key = "name";

    setenv_impl(key,"Eric", 1);
    printf("%s\n", getenv(key));

    unsetenv_impl(key);

    char *val = getenv(key);
    printf("%s\n", val==NULL?"NULL":getenv(key));

    return 0;
}

int main(int argc, void *argv[]) {
    // setenv_impl_test();
    unsetenv_impl_test();

    return 0;
}

В моем setevn_impl() я использую malloc() для выделения памяти для новой переменной среды.

Но я не знаю, как распределяется память среды процесса по умолчанию.

Мой вопрос:

  • В моей реализации unsetenv_impl() необходимо/правильно ли освобождать память удаленной строки среды с помощью free()?

  • Если я не освобожу его, будет ли это проблемой, или он не займет много памяти, поэтому его можно игнорировать?


Совет:

putenv() не будет дублировать строку, она просто заставит глобальную переменную environ указывать на строку, которая ей передается.


person user218867    schedule 26.05.2015    source источник


Ответы (1)


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

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

Ожидается, что некоторые серверы будут работать круглосуточно и без выходных. В этих случаях любая утечка любого рода означает, что ваш сервер в конечном итоге исчерпает этот ресурс и каким-то образом зависнет / выйдет из строя. Коротенькая утилита, да утечка не так уж и плоха. Любой сервер, любая утечка — это смерть. Сделайте себе одолжение. Убирать за собой. это хорошая привычка

person Vinay Shukla    schedule 26.05.2015
comment
Итак, мне нужно отслеживать новые переменные, которые я добавил вручную, чтобы я мог освободить их, как только они мне больше не понадобятся? Мне интересно, как они реализуют это в исходном коде Linux, чтобы избежать утечки памяти... - person user218867; 26.05.2015
comment
Отличный способ сделать это — не бросать вызовы malloc() и free() по всей кодовой базе. Централизуйте их в две функции, тогда у вас будет одна точка для всех проверок, которая также учитывается. Подробный пример можно найти здесь. stackoverflow.com/a/2983953/2959769 - person Vinay Shukla; 26.05.2015