如何使用 putenv 系统调用来维护内存?
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!
}
我现在的问题是……环境变量内存如何释放
?是否需要将其单独存储并不断从环境中移除物品?即
#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)
*/
The POSIX system call putenv
states that the allocated memory string cannot be freed by the caller after the call to putenv
. 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 at this point is ... how is the environment variable memory free
'd? Does one need to maintain their on separate storage 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 does look 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)
*/
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
不,您不需要手动执行此操作。当进程退出时,操作系统会释放环境内存(作为进程内存的一部分)。
No, you don't need to do that manually. Memory for your environment is freed by the OS (as part of your process memory) when your process exits.
如果您担心内存泄漏。
这就是为什么 POSIX 提供
setenv()
和unsetenv()
以及 - 它们控制内存并管理它。引用
putenv()
手册页(上面的 URL):Don't use
putenv()
if you are worried about the memory leaking.That's why POSIX provides
setenv()
andunsetenv()
as well - those take control of the memory and manage it.Quoting the
putenv()
manual page (URL above):