C 试图收集我的linux环境的环境变量,但我不断遇到分段错误
尝试打印环境变量,将它们存储到令牌上,将所述令牌放入数组,然后使用冒泡排序对它们进行排序。 到目前为止,我无法将它们放在阵列上而不遇到分段错误C 试图收集我的linux环境的环境变量,但我不断遇到分段错误,c,C,尝试打印环境变量,将它们存储到令牌上,将所述令牌放入数组,然后使用冒泡排序对它们进行排序。 到目前为止,我无法将它们放在阵列上而不遇到分段错误 #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX 100 #define MIN 5 int main(int argc, char *argv[], char *envp[]) { int i = 0; char *de
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 100
#define MIN 5
int main(int argc, char *argv[], char *envp[])
{
int i = 0;
char *delimiter;
delimiter= ".:;";
char *token;
char *tokenArray[50];
while(envp[i])
{
//token = malloc(20*sizeof(char));
token = strtok(envp[i], delimiter);
printf(" %s \n", token);
token = strtok(NULL, delimiter);
tokenArray[i] = malloc(50);
strcpy(tokenArray[i], token);
//free(token);
i++;
}
for(int j = 0; j < i; j++)
{
printf(" %s \n ", tokenArray[j]);
free(tokenArray[j]);
}
return 0;
}
#包括
#包括
#包括
#定义最大值100
#定义最小值5
int main(int argc,char*argv[],char*envp[]
{
int i=0;
字符*分隔符;
分隔符=“.:;”;
字符*令牌;
char*tokenArray[50];
while(envp[i])
{
//令牌=malloc(20*sizeof(char));
token=strtok(envp[i],分隔符);
printf(“%s\n”,标记);
token=strtok(空,分隔符);
令牌数组[i]=malloc(50);
strcpy(令牌数组[i],令牌);
//免费(代币);
i++;
}
对于(int j=0;j
这是一段工作代码,它将所有环境变量放入标记中
int main(int argc, char *argv[], char *envp[])
{
const char *delimiter = "=";
// Calculate the number of env variables. This is much better than
// assuming a maximum size.
size_t no_env = 0;
while(envp[no_env])
no_env++;
// Allocate space for no_env pointers
char **tokens = malloc(sizeof(*tokens) * no_env);
for(int i=0; i<no_env; i++)
{
// Token is not used outside this loop, so there's no point in declaring
// it outside. Same goes for the indexing variable i.
char *token = strtok(envp[i], delimiter);
// Allocate space for the string
tokens[i] = malloc(strlen(token) * sizeof(*tokens[i]));
strcpy(tokens[i], token);
}
// Free all the strings and then the last pointer
for(int i = 0; i < no_env; i++)
free(tokens[i]);
free(tokens);
}
对于您的代码,您可以使用一个简单的if(!(p=malloc(…){return EXIT_FAILURE;}
来代替所有这些goto
语句
使用malloc
时,请始终使用p=malloc(sizeof(*p)*size)
。这样可以显著降低出错风险。如果要为字符串(char)分配空间,则可以跳过sizeof
,直接进入p=malloc(size)
但请确保您知道自己在做什么。虽然不清楚为什么要使用分隔符=“.:;”;
对每个环境变量进行日化,但它没有任何问题(我也会添加“*”
),而不是在环境变量上循环两次(一次计算分配指针的数量,下一次将变量标记为单个标记),您只需根据需要对envp
一次和realloc
指针进行迭代即可
从一定数量的指针开始(比如2
),然后将使用的指针与可用的(avail
)指针数量进行比较,当它们相等时,将realloc
可用的指针数量增加一倍
另一个注意事项。strtok
在标记化时修改原始字符串。因此,您可以(可选)在标记化副本之前简单地复制环境,而不是直接标记化envp[x]
,从而修改envp
中的内容
分配和重新分配指针,然后为每个令牌分配存储的简短实现可以是:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NPTRS 2 /* if you need a constant, #define one (or more) */
#define MAXC 8192
int main (int argc, char *argv[], char *envp[])
{
size_t i = 0, used = 0, avail = NPTRS; /* counters */
const char *delim = ".:;*"; /* delimiters */
char **tarray = NULL; /* pointer to pointer */
/* allocate/validate NPTRS pointers initially */
if (!(tarray = malloc (avail * sizeof *tarray))) {
perror ("malloc-tarray");
return 1;
}
while (envp[i]) { /* loop over each env var */
char envstr[MAXC]; /* array to hold current env var */
size_t envlen = strlen (envp[i]); /* get env var len */
/* tokenize envp[i] */
if (envlen >= MAXC - 1) { /* check env fits in envstr */
fputs ("error: envstr exceeds MAXC chars.\n", stderr);
continue;
}
/* strtok modifies original, make copy of env var before strtok */
memcpy (envstr, envp[i], envlen + 1);
/* tokenize env var based on delim */
for (char *p = strtok (envstr, delim); p; p = strtok (NULL, delim)) {
size_t len = strlen (p);/* length of token */
if (used == avail) { /* check if realloc of pointers req'd */
/* always realloc using a temporary pointer */
void *tmp = realloc (tarray, 2 * avail * sizeof *tarray);
if (!tmp) { /* validate reallocation */
perror ("realloc-tarray");
goto done; /* tarray still good, break nested loops */
}
tarray = tmp; /* assign realloc'ed block to tarray */
avail *= 2; /* update avaialble no. of pointers */
}
/* allocate/validate storage for token */
if (!(tarray[used] = malloc (len + 1))) {
perror ("malloc tarray[used]");
goto done; /* goto req'd to break nested loops */
}
memcpy (tarray[used++], p, len + 1); /* copy to new memory */
}
i++; /* advance to next environment variable */
}
done:;
for (i = 0; i < used; i++) { /* output all tokens */
printf ("tarray[%3zu] : %s\n", i, tarray[i]);
free (tarray[i]); /* free storage of strings */
}
free (tarray); /* free pointers */
(void)argc, (void)argv; /* suppress unused varaible warnings */
}
始终确认已释放所有已分配的内存,并且没有内存错误。是否尝试运行调试器以查看代码在哪一行崩溃?您是否了解指针和内存分配是如何工作的?您不止一次设置了指向malloc的指针(某个东西),然后在随后的一行中覆盖它,从而导致内存泄漏。我读了至少五个教程,同一点出现了多次。这些教程都说,每次调用malloc时,内存中的地址都会被分配。当然,接下来我会访问类似Stack的网站,显然它的工作方式不同,因为调用malloc multiLE时代意味着我在写最后一个内存调用,当我检查“在线教程”时,他们从不提任何东西,除了每个Maloc都有它自己的内存地址。好,让我们举一个小例子。如果我们采用这个代码:<代码> int x;x=5;x=3;< /代码>我认为很明显,<代码> x=5 < /代码>没有任何影响。这和指针没什么不同。有点像,但也不完全一样。每个malloc都应该有一个空闲的。但是这两个代码片段是100%等效的:char*p=malloc(1);p=“foo”
,malloc(1);char*p=“foo”
。对malloc的调用除了导致内存泄漏之外没有任何效果。而不是strlen()
/malloc()
pair请使用strdup()
。它完全满足您的需要,让您的意图更加清晰。@如果该函数是标准的一部分,我会很忙,但事实并非如此。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NPTRS 2 /* if you need a constant, #define one (or more) */
#define MAXC 8192
int main (int argc, char *argv[], char *envp[])
{
size_t i = 0, used = 0, avail = NPTRS; /* counters */
const char *delim = ".:;*"; /* delimiters */
char **tarray = NULL; /* pointer to pointer */
/* allocate/validate NPTRS pointers initially */
if (!(tarray = malloc (avail * sizeof *tarray))) {
perror ("malloc-tarray");
return 1;
}
while (envp[i]) { /* loop over each env var */
char envstr[MAXC]; /* array to hold current env var */
size_t envlen = strlen (envp[i]); /* get env var len */
/* tokenize envp[i] */
if (envlen >= MAXC - 1) { /* check env fits in envstr */
fputs ("error: envstr exceeds MAXC chars.\n", stderr);
continue;
}
/* strtok modifies original, make copy of env var before strtok */
memcpy (envstr, envp[i], envlen + 1);
/* tokenize env var based on delim */
for (char *p = strtok (envstr, delim); p; p = strtok (NULL, delim)) {
size_t len = strlen (p);/* length of token */
if (used == avail) { /* check if realloc of pointers req'd */
/* always realloc using a temporary pointer */
void *tmp = realloc (tarray, 2 * avail * sizeof *tarray);
if (!tmp) { /* validate reallocation */
perror ("realloc-tarray");
goto done; /* tarray still good, break nested loops */
}
tarray = tmp; /* assign realloc'ed block to tarray */
avail *= 2; /* update avaialble no. of pointers */
}
/* allocate/validate storage for token */
if (!(tarray[used] = malloc (len + 1))) {
perror ("malloc tarray[used]");
goto done; /* goto req'd to break nested loops */
}
memcpy (tarray[used++], p, len + 1); /* copy to new memory */
}
i++; /* advance to next environment variable */
}
done:;
for (i = 0; i < used; i++) { /* output all tokens */
printf ("tarray[%3zu] : %s\n", i, tarray[i]);
free (tarray[i]); /* free storage of strings */
}
free (tarray); /* free pointers */
(void)argc, (void)argv; /* suppress unused varaible warnings */
}
$ ./bin/main_envp
tarray[ 0] : XDG_VTNR=7
tarray[ 1] : LESSKEY=/etc/lesskey
tarray[ 2] : bin
tarray[ 3] : MANPATH=/usr/local/man
tarray[ 4] : /usr/share/man
tarray[ 5] : /opt/kde3/share/man
tarray[ 6] : NNTPSERVER=news
tarray[ 7] : XDG_SESSION_ID=1
tarray[ 8] : SSH_AGENT_PID=3195
tarray[ 9] : KDE_MULTIHEAD=false
tarray[ 10] : HOSTNAME=wizard
tarray[ 11] : DM_CONTROL=/var/run/xdmctl
<snip>
$ valgrind ./bin/main_envp
==16243== Memcheck, a memory error detector
==16243== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==16243== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==16243== Command: ./bin/main_envp
==16243==
tarray[ 0] : XDG_VTNR=7
tarray[ 1] : LESSKEY=/etc/lesskey
tarray[ 2] : bin
tarray[ 3] : MANPATH=/usr/local/man
tarray[ 4] : /usr/share/man
tarray[ 5] : /opt/kde3/share/man
tarray[ 6] : NNTPSERVER=news
tarray[ 7] : XDG_SESSION_ID=1
tarray[ 8] : SSH_AGENT_PID=3195
tarray[ 9] : KDE_MULTIHEAD=false
tarray[ 10] : HOSTNAME=wizard
tarray[ 11] : DM_CONTROL=/var/run/xdmctl
<snip>
==16243==
==16243== HEAP SUMMARY:
==16243== in use at exit: 0 bytes in 0 blocks
==16243== total heap usage: 292 allocs, 292 frees, 11,723 bytes allocated
==16243==
==16243== All heap blocks were freed -- no leaks are possible
==16243==
==16243== For counts of detected and suppressed errors, rerun with: -v
==16243== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)