我一直在思考环境变量,并有一些问题/意见。
putenv(char *string);
这个调用似乎有致命的缺陷。因为它不复制传递的字符串,所以你不能用本地调用它,并且不能保证堆分配的字符串不会被覆盖或意外删除。此外(虽然我没有测试过),因为环境变量的一种用途是将值传递给 child 的环境,如果 child 调用 exec*() 函数之一,这似乎没用。我错了吗?
Linux 手册页表明 glibc 2.0-2.1.1 放弃了上述行为并开始复制字符串,但这导致了内存泄漏,已在 glibc 2.1.2 中修复。我不清楚这个内存泄漏是什么或如何修复的。
setenv() 复制字符串,但我不知道它是如何工作的。进程加载时为环境分配空间,但它是固定的。这里有一些(任意的?)约定吗?例如,在 env 字符串指针数组中分配比当前使用更多的插槽,并根据需要向下移动空终止指针?新的(复制的)字符串的内存是否分配在环境本身的地址空间中,如果它太大而无法容纳您只需获得 ENOMEM?
考虑到上述问题,有什么理由更喜欢 putenv() 而不是 setenv()?
最佳答案
- [The]
putenv(char *string);[...] call seems fatally flawed.
是的,它有致命的缺陷。 它被保存在 POSIX (1988) 中,因为那是现有技术。 更正: POSIX 1990 标准在 §B.4.6.1 中说“附加函数 putenv() 和 clearenv() 被考虑但被拒绝”。 Single Unix Specification (SUS) 1997 年的第 2 版列出了 setenv() 机制稍后出现。putenv(),但没有列出 setenv() 或 unsetenv()。下一个版本 (2004) 确实定义了 setenv()和 unsetenv()也是。
Because it doesn't copy the passed string you can't call it with a local and there is no guarantee a heap allocated string won't be overwritten or accidentally deleted.
你说得对,将局部变量传递给 putenv() 几乎总是一个糟糕的选择——异常模糊到几乎不存在的地步。如果字符串是在堆上分配的(使用 malloc() 等),您必须确保您的代码不会修改它。如果是,则同时在修改环境。
Furthermore (though I haven't tested it), since one use of environment variables is to pass values to child's environment this seems useless if the child calls one of the
exec*()functions. Am I wrong in that?
exec*() 函数制作环境的副本并将其传递给执行的进程。那里没有问题。
The Linux man page indicates that glibc 2.0-2.1.1 abandoned the above behavior and began copying the string but this led to a memory leak that was fixed in glibc 2.1.2. It's not clear to me what this memory leak was or how it was fixed.
内存泄漏的出现是因为一旦你用一个字符串调用了 putenv(),你就不能再出于任何目的使用该字符串,因为你无法判断它是否仍在使用,尽管你可以通过覆盖来修改值(如果将名称更改为在环境中另一个位置找到的环境变量的名称,则结果不确定)。所以,如果你已经分配了空间,经典的 putenv() 如果你再次更改变量就会泄漏它。当 putenv() 开始复制数据时,分配的变量变为未引用,因为 putenv() 不再保留对参数的引用,但用户期望环境将引用它,所以内存被泄露了。我不确定修复是什么——我 3/4 预计它会恢复到旧的行为。
setenv()copies the string but I don't know exactly how that works. Space for the environment is allocated when the process loads but it is fixed.
原来的环境空间是固定的;当你开始修改它时,规则就会改变。即使使用 putenv(),原始环境也会被修改,并且可能会因添加新变量或将现有变量更改为更长的值而增长。
Is there some (arbitrary?) convention at work here? For example, allocating more slots in the env string pointer array than currently used and moving the null terminating pointer down as needed?
这就是 setenv() 机制可能会做的事情。 (全局)变量 environ 指向环境变量指针数组的开头。如果它一次指向一个内存块,另一个时间指向另一个 block ,那么环境就被切换了,就这样。
Is the memory for the new (copied) string allocated in the address space of the environment itself and if it is too big to fit you just get ENOMEM?
嗯,是的,您可以获得 ENOMEM,但您必须非常努力。如果你将环境扩展得太大,你可能无法正确执行其他程序——要么环境被截断,要么执行操作失败。
Considering the above issues, is there any reason to prefer putenv() over setenv()?
setenv()。setenv(),但不要将其作为首要任务。putenv()。关于c - 关于 putenv() 和 setenv() 的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5873029/
我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po
尝试通过RVM将RubyGems升级到版本1.8.10并出现此错误:$rvmrubygemslatestRemovingoldRubygemsfiles...Installingrubygems-1.8.10forruby-1.9.2-p180...ERROR:Errorrunning'GEM_PATH="/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/ruby-1.9.2-p180@global:/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/rub
我的最终目标是安装当前版本的RubyonRails。我在OSXMountainLion上运行。到目前为止,这是我的过程:已安装的RVM$\curl-Lhttps://get.rvm.io|bash-sstable检查已知(我假设已批准)安装$rvmlistknown我看到当前的稳定版本可用[ruby-]2.0.0[-p247]输入命令安装$rvminstall2.0.0-p247注意:我也试过这些安装命令$rvminstallruby-2.0.0-p247$rvminstallruby=2.0.0-p247我很快就无处可去了。结果:$rvminstall2.0.0-p247Search
由于fast-stemmer的问题,我很难安装我想要的任何rubygem。我把我得到的错误放在下面。Buildingnativeextensions.Thiscouldtakeawhile...ERROR:Errorinstallingfast-stemmer:ERROR:Failedtobuildgemnativeextension./System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/rubyextconf.rbcreatingMakefilemake"DESTDIR="cleanmake"DESTDIR=
当我尝试安装Ruby时遇到此错误。我试过查看this和this但无济于事➜~brewinstallrubyWarning:YouareusingOSX10.12.Wedonotprovidesupportforthispre-releaseversion.Youmayencounterbuildfailuresorotherbreakages.Pleasecreatepull-requestsinsteadoffilingissues.==>Installingdependenciesforruby:readline,libyaml,makedepend==>Installingrub
我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www
我意识到这可能是一个非常基本的问题,但我现在已经花了几天时间回过头来解决这个问题,但出于某种原因,Google就是没有帮助我。(我认为部分问题在于我是一个初学者,我不知道该问什么......)我也看过O'Reilly的RubyCookbook和RailsAPI,但我仍然停留在这个问题上.我找到了一些关于多态关系的信息,但它似乎不是我需要的(尽管如果我错了请告诉我)。我正在尝试调整MichaelHartl'stutorial创建一个包含用户、文章和评论的博客应用程序(不使用脚手架)。我希望评论既属于用户又属于文章。我的主要问题是:我不知道如何将当前文章的ID放入评论Controller。
首先回顾一下拉格朗日定理的内容:函数f(x)是在闭区间[a,b]上连续、开区间(a,b)上可导的函数,那么至少存在一个,使得:通过这个表达式我们可以知道,f(x)是函数的主体,a和b可以看作是主体函数f(x)中所取的两个值。那么可以有, 也就意味着我们可以用来替换 这种替换可以用在求某些多项式差的极限中。方法: 外层函数f(x)是一致的,并且h(x)和g(x)是等价无穷小。此时,利用拉格朗日定理,将原式替换为 ,再进行求解,往往会省去复合函数求极限的很多麻烦。使用要注意:1.要先找到主体函数f(x),即外层函数必须相同。2.f(x)找到后,复合部分是等价无穷小。3.要满足作差的形式。如果是加
SPI接收数据左移一位问题目录SPI接收数据左移一位问题一、问题描述二、问题分析三、探究原理四、经验总结最近在工作在学习调试SPI的过程中遇到一个问题——接收数据整体向左移了一位(1bit)。SPI数据收发是数据交换,因此接收数据时从第二个字节开始才是有效数据,也就是数据整体向右移一个字节(1byte)。请教前辈之后也没有得到解决,通过在网上查阅前人经验终于解决问题,所以写一个避坑经验总结。实际背景:MCU与一款芯片使用spi通信,MCU作为主机,芯片作为从机。这款芯片采用的是它规定的六线SPI,多了两根线:RDY和INT,这样从机就可以主动请求主机给主机发送数据了。一、问题描述根据从机芯片手
文章目录git常用命令(简介,详细参数往下看)Git提交代码步骤gitpullgitstatusgitaddgitcommitgitpushgit代码冲突合并问题方法一:放弃本地代码方法二:合并代码常用命令以及详细参数gitadd将文件添加到仓库:gitdiff比较文件异同gitlog查看历史记录gitreset代码回滚版本库相关操作远程仓库相关操作分支相关操作创建分支查看分支:gitbranch合并分支:gitmerge删除分支:gitbranch-ddev查看分支合并图:gitlog–graph–pretty=oneline–abbrev-commit撤消某次提交git用户名密码相关配置g