Как сохранить память с помощью системного вызова putenv? - PullRequest
9 голосов
/ 24 января 2011

Системный вызов POSIX putenv сообщает, что выделенная строка памяти не может быть освобождена вызывающей стороной после вызова putenv.Следовательно, вы не можете вызвать putenv с автоматической переменной.

Пример:

#include <cstdlib>
#include <cstring>
#include <unistd.h>

int main()
{
    char envVar[] = "MYVAR=Value";
    // putenv(envVar); //ERROR!
    char *memory = static_cast<char*>(std::malloc(sizeof(envVar)));
    std::strcpy(memory, envVar);
    putenv(memory); //OK!
}

На данный момент у меня вопрос ... какова переменная среды памяти free '?Нужно ли хранить их на отдельном хранилище и постоянно удалять вещи из окружающей среды?Т.е.

#include <cstdlib>
#include <cstring>
#include <string>
#include <map>

static std::map<std::string, char*> environmentBlock;

static struct EnvironmentBlockFreer
{
    ~EnvironmentBlockFreer()
    {
        for(std::map<std::string, char*>::iterator it = environmentBlock.begin()
            it != environmentBlock.end(); ++it)
        {
            putenv(it->first.c_str()); //Remove entry from the environment
            std::free(static_cast<void *>(it->second)); //Nuke the memory
        }
    }
} EnvironmentBlockFreer_ENTRY;

int main()
{
    char envVar[] = "MYVAR=Value";
    char *memory = static_cast<char*>(std::malloc(sizeof(envVar)));
    std::strcpy(memory, envVar);
    putenv(memory); //OK!
    environmentBlock.insert(std::pair<std::string, char*>(
        "MYVAR", memory)); //Remember the values for later!
}

РЕДАКТИРОВАТЬ: Похоже, мне нужно отслеживать это сам, по крайней мере в соответствии с Valgrind:

/* This program: */

#include <stdlib.h>
#include <string.h>

int main()
{
        char str[] = "MYVAR=Example";
        char *mem = malloc(sizeof(str));
        strcpy(mem, str);
        putenv(mem);
}

/* Produced output:

==4219== Memcheck, a memory error detector
==4219== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==4219== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
==4219== Command: ./a.out
==4219== 
==4219== 
==4219== HEAP SUMMARY:
==4219==     in use at exit: 14 bytes in 1 blocks
==4219==   total heap usage: 2 allocs, 1 frees, 194 bytes allocated
==4219== 
==4219== LEAK SUMMARY:
==4219==    definitely lost: 14 bytes in 1 blocks
==4219==    indirectly lost: 0 bytes in 0 blocks
==4219==      possibly lost: 0 bytes in 0 blocks
==4219==    still reachable: 0 bytes in 0 blocks
==4219==         suppressed: 0 bytes in 0 blocks
==4219== Rerun with --leak-check=full to see details of leaked memory
==4219== 
==4219== For counts of detected and suppressed errors, rerun with: -v
==4219== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 13 from 8)
*/

Ответы [ 2 ]

15 голосов
/ 24 января 2011

Не используйте putenv(), если вас беспокоит утечка памяти.

Вот почему POSIX также предоставляет setenv() и unsetenv() - они контролируют память и управляют ею.


Цитирование справочной страницы putenv() (URL выше):

Функция putenv() должна использовать аргумент string для установки значений переменных среды. Аргумент string должен указывать на строку вида "name= value". Функция putenv() должна сделать значение переменной среды name равным value путем изменения существующей переменной или создания новой. В любом случае строка, указанная string , должна стать частью среды, поэтому изменение строки должно изменить среду. Пространство, используемое string , больше не используется, когда новая строка, которая определяет name , передается в putenv().

2 голосов
/ 24 января 2011

Нет, вам не нужно делать это вручную. При выходе из процесса ОС освобождает память для вашей среды (как часть памяти процесса).

...