我有一份学校作业,一切都很好,除了一部分,我无法弄清楚。以下是我的问题发生的代码片段:
//something goes wrong here, wont copy over
puts("bravo");
//add to end of the list
int size_list = sizeof(environ);
//char** tmp_ptr = ( char** )calloc( size_list + 1, ( size_list + 1 ) * sizeof( char* ) );
char** tmp_ptr = ( char** ) malloc ( ( size_list + 1 ) * sizeof( char* ) );
int k;
for ( k = 0; k < size_list; ++k )
{
tmp_ptr[k] = environ[k];
//memcpy(tmp_ptr[k],environ[k],sizeof(environ[k]));
}
//char** tmp_ptr= (char**)realloc(*environ, size_list+2);
environ = tmp_ptr;
environ[size_list] = (char*)malloc(len_string+1);
strcpy(environ[size_list],full_string);
return 1;
您可以忽略“bravo”,我可以找到问题发生的位置。我试图让environ获得新的变量列表,但是当我将它设置为等于tmp_ptr时,它是空的。我很确定这些值会被复制,但我不知道出了什么问题。 当函数结束时,tmp_ptr中的数据是否会被删除?这是一个可能的解释吗?如何正确分配和复制内存。我尝试使用realloc,但这给了我无效的指针错误,所以我依赖于calloc或malloc。提前谢谢。
答案 0 :(得分:4)
environ
的长度不是sizeof(environ)
,因为environ
是char **
(因此sizeof(environ)
是4或8,具体取决于您的平台) 。您正在做的是有效地消除大部分environ
,因为您只复制了前几个条目。
要了解environ
中有多少条目,请执行
int cnt = 0;
char **envp = environ;
while(*envp++) cnt++;
我还应该注意这个方法的问题:因为environ
是一个NULL
- 终止的字符串数组(不要与'以null结尾的字符串'混淆),你必须用您自己的条目替换最后的NULL
,然后在新条目后添加新的NULL
。目前,您的代码(如果正确计算了大小)会在NULL
之后添加您的条目,并且该程序无法显示。
旁注:绝对不建议以这种方式搞乱environ
。请改用getenv
/ setenv
;如果您需要批量设置环境,请尝试使用execve
。 (因此,在您的情况下,您只需setenv("varname", "varvalue", 1)
将varname=varvalue
添加到环境中(如果已设置,则将现有映射替换为varname
。)
答案 1 :(得分:3)
environ
是一个指针,意味着sizeof(environ)
不是该数组中的项目数。相反,它是指针的大小,在你的情况下大概是四或八。
如果environ
与argv
(一个字符指针数组,其中最后一个是空指针)的结构相同,则需要通过遍历数组来确定其大小,直到你找到了NULL。
像(未经测试,但想法是合理的):
char **envPtr = environ;
int size_list = 0; // probably should be size_t
while (*envPtr != NULL) {
envPtr++;
size_list++;
}
你可以在这个完整的程序中看到效果(通过一些更改来解决其他一些错误):
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define full_string "xyzzy=plugh"
#define len_string strlen(full_string)
int main (int argc, char **argv) {
int k, size_list = sizeof(environ);
char **tmp_ptr = malloc ((size_list + 1) * sizeof ( char*));
for (k = 0; k < size_list; ++k) printf ("[%s]\n", environ[k]);
for (k = 0; k < size_list; ++k) tmp_ptr[k] = environ[k];
tmp_ptr[size_list] = NULL;
environ = tmp_ptr;
environ[size_list] = malloc (len_string + 1);
strcpy(environ[size_list],full_string);
printf ("=====\n");
for (k = 0; k <= size_list; ++k) printf ("[%s]\n", environ[k]);
return 0;
}
这只输出了四个环境变量,因为我有四个字节的指针:
[ORBIT_SOCKETDIR=/tmp/orbit-pax]
[SSH_AGENT_PID=1978]
[GPG_AGENT_INFO=/tmp/seahorse-tNDhG9/S.gpg-agent:2005:1]
[TERM=xterm]
=====
[ORBIT_SOCKETDIR=/tmp/orbit-pax]
[SSH_AGENT_PID=1978]
[GPG_AGENT_INFO=/tmp/seahorse-tNDhG9/S.gpg-agent:2005:1]
[TERM=xterm]
[xyzzy=plugh]
更改代码以正确确定环境的大小:
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define full_string "xyzzy=plugh"
#define len_string strlen(full_string)
int main(int argc, char **argv) {
int k, size_list = 0;
char **envPtr = environ;
while (*envPtr != NULL) {
envPtr++;
size_list++;
}
char **tmp_ptr = malloc ((size_list + 1) * sizeof (char*));
for (k = 0; k < size_list; ++k) printf ("[%s]\n", environ[k]);
for (k = 0; k < size_list; ++k) tmp_ptr[k] = environ[k];
tmp_ptr[size_list] = NULL;
environ = tmp_ptr;
environ[size_list] = malloc (len_string + 1);
strcpy(environ[size_list],full_string);
printf ("=====\n");
for (k = 0; k <= size_list; ++k) printf ("[%s]\n", environ[k]);
return 0;
}
给了我很多:
[ORBIT_SOCKETDIR=/tmp/orbit-pax]
[SSH_AGENT_PID=1978]
[GPG_AGENT_INFO=/tmp/seahorse-tNDhG9/S.gpg-agent:2005:1]
[TERM=xterm]
[SHELL=/bin/bash]
[GTK_RC_FILES=/etc/gtk/gtkrc:/home/pax/.gtkrc-1.2-gnome2]
[WINDOWID=62914564]
[GNOME_KEYRING_CONTROL=/tmp/keyring-RADe9n]
[GTK_MODULES=canberra-gtk-module]
[USER=pax]
:
[XAUTHORITY=/var/run/gdm3/auth-for-pax-AO1dYc/database]
[_=./testprog]
=====
[ORBIT_SOCKETDIR=/tmp/orbit-pax]
[SSH_AGENT_PID=1978]
[GPG_AGENT_INFO=/tmp/seahorse-tNDhG9/S.gpg-agent:2005:1]
[TERM=xterm]
[SHELL=/bin/bash]
[GTK_RC_FILES=/etc/gtk/gtkrc:/home/pax/.gtkrc-1.2-gnome2]
[WINDOWID=62914564]
[GNOME_KEYRING_CONTROL=/tmp/keyring-RADe9n]
[GTK_MODULES=canberra-gtk-module]
[USER=pax]
:
[XAUTHORITY=/var/run/gdm3/auth-for-pax-AO1dYc/database]
[_=./testprog]
[xyzzy=plugh]
对于它的价值,您的代码存在以下问题:
malloc
转换返回值 - 这在C中是不明智的,因为它可能导致您隐藏代码问题。除了上一个之外的所有这些都在我上面的最终代码示例中修复。