【问题标题】:How does one maintain memory with the putenv system call?如何使用 putenv 系统调用来维护内存?
【发布时间】:2011-06-14 06:09:04
【问题描述】:

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'd 怎么样?是否需要将它们保存在单独的存储中并不断从环境中移除东西?即

#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)
*/

【问题讨论】:

  • 我不会打扰 malloc/free,将字符串存储在您的地图中并将它们的 c_str 传递给 putenv。只要不需要putenv的荒谬特性,可以通过写入字符串来修改环境,就是……
  • @Steve -- 这些只是我在 5 分钟内完成的垃圾测试......不是真正的代码 :) 如果putenv 实际上在内存块上调用了free,我不想造成问题所以我使用了malloc
  • 在这种情况下,我会说,“是的,但是看在上帝的份上,通过使用更好的 C++ 接口来复制用户提供的字符串来包围 putenv”。

标签: c++ unix system-calls


【解决方案1】:

如果您担心内存泄漏,请不要使用putenv()

这就是 POSIX 提供 setenv()unsetenv() 的原因 - 它们控制并管理内存。


引用putenv() 手册页(以上网址):

putenv() 函数应使用 string 参数来设置环境变量值。 string 参数应指向格式为“name= value”的字符串。 putenv() 函数应通过更改现有变量或创建新变量使环境变量 name 的值等于 value。在任何一种情况下,string 指向的字符串都将成为环境的一部分,因此更改字符串将改变环境。一旦将定义 name 的新字符串传递给 putenv()string 使用的空间将不再使用。

【讨论】:

    【解决方案2】:

    不,您不需要手动执行此操作。当您的进程退出时,操作系统会释放您环境的内存(作为进程内存的一部分)。

    【讨论】:

    • 环境变量被覆盖了怎么办?
    • 我猜如果您对环境进行了很多项更改,或者您正在使用检漏仪并希望消除误报;那么仅仅泄漏要由操作系统清理的内存是不可接受的。原则上,这里的环境没有什么特别之处,你也可以说任何内存都可能泄漏,尤其是如果它是 O(1) 的内存量。
    猜你喜欢
    • 1970-01-01
    • 2014-05-12
    • 2010-09-20
    • 2015-01-13
    • 1970-01-01
    • 2011-04-20
    • 1970-01-01
    • 2016-01-06
    • 2022-07-19
    相关资源
    最近更新 更多