How to save memory during putenv system call?

The POSIX putenv system call indicates that the allocated memory line cannot be freed by the caller after the putenv call. Therefore, you cannot call putenv with an automatic variable.

Example:

 #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! } 

My question is at this point ... how is the environment variable free 'd? Do I need to maintain them in a separate repository and constantly remove things from the environment? I.e.

 #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! } 

EDIT: it looks like I need to track this myself, at least according to 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) */ 
+8
c ++ unix system-calls
source share
2 answers

Do not use putenv() if you are worried about a memory leak.

This is why POSIX provides setenv() and unsetenv() , those who control and manage memory.


Quoting the putenv() page (URL above):

The putenv() function must use a string argument to set the values โ€‹โ€‹of environment variables. The string argument must point to a string of the form " name= value ". The putenv() function must make the value of the name of the environment variable equal to the value by changing the existing variable or creating a new one. In any case, the line pointed to by the line should become part of the environment, so changing the line should change the environment. The space used by the string is no longer used when the new string that defines the name is passed to putenv() .

+15
source share

No, you do not need to do this manually. The memory for your environment is freed by the OS (as part of your process memory) when your process terminates.

+2
source share

Source: https://habr.com/ru/post/651423/


All Articles