如何使用 putenv 系统调用来维护内存?

发布于 2024-10-14 01:07:55 字数 2632 浏览 5 评论 0原文

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

木落 2024-10-21 01:07:55

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

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.

呆° 2024-10-21 01:07:55

如果您担心内存泄漏。

这就是为什么 POSIX 提供 setenv()unsetenv() 以及 - 它们控制内存并管理它。


引用 putenv() 手册页(上面的 URL):

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

Don't use putenv() if you are worried about the memory leaking.

That's why POSIX provides setenv() and unsetenv() as well - those take control of the memory and manage it.


Quoting the putenv() manual page (URL above):

The putenv() function shall use the string argument to set environment variable values. The string argument should point to a string of the form "name= value". The putenv() function shall make the value of the environment variable name equal to value by altering an existing variable or creating a new one. In either case, the string pointed to by string shall become part of the environment, so altering the string shall change the environment. The space used by string is no longer used once a new string which defines name is passed to putenv().

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文