2017-03-04 22 views
2

我有一个小问题(很大)的c程序,并发现问题不是来自我的程序本身,而是我创建我的数组的方式,我认为。C - 数组值消失,而最后设置为空

我的问题是,我需要创建一个与包含环境变量(extern char **environ)相同的数组,然后在最后添加另一个值。

这里是我做了检查,如果environ很好复制或不是代码:

#include <stdlib.h> 
#include <string.h> 
#include <stdio.h> 

int ft_length(char **arr) 
{ 
    int i = 0; 

    while (arr[i]) 
     i++; 
    return (i); 
} 

int main(void) 
{ 
    extern char **environ; 
    char **env; 
    int err; 
    int x; 

    err = 0; 
    x = 0; 
    env = (char**)malloc(sizeof(char*) * ft_length(environ) + 2); 
    while (environ[x]) 
    { 
    // printf("%s\n", environ[x]); 
     env[x] = (char*)malloc(sizeof(char) * strlen(environ[x]) + 1); 
     bzero(env[x], strlen(environ[x])); 
     strncpy(env[x], environ[x], strlen(environ[x])); 
    // printf("%s\n", env[x]); 
     x++; 
    } 
    env[x] = (char*)malloc(sizeof(char) * 4); 
    env[x] = "ccc\0"; 
    env[++x] = NULL; 
    x = 0; 
    while (environ[x]) 
    { 
     if (strcmp(environ[x], env[x]) != 0) 
     { 
      err++; 
      printf("error on env[%d]\n", x); 
      printf("environ[%d] : |%s|\n", x, environ[x]); 
      printf("env[%d] : |%s|\n", x, env[x]); 
      printf("----------------\n"); 
     } 
     x++; 
    } 
    while (env[x]) 
    { 
     if (strcmp(env[x], "ccc") != 0) 
     { 
      err++; 
      printf("env[%d] contain |%s| instead of |ccc|\n", x, env[x]); 
     } 
     x++; 
    } 
    printf("done with %d error(s)\n", err); 
    return (1); 
} 

当我运行在Mac OSX上的代码,env[0]是在结束空,这种情况发生当我设置最后一个数组值为NULLenv[++x] = NULL)。但是,如果我想在没有segfault的情况下打印我的数组,我需要这一个是NULL

因此,首先我想知道我的代码是否在某处出错?

我试着在我的Linux电脑上运行这段代码(Ubuntu 16.04),看起来没有问题。

+2

“A * B + C”被解析为“(A * B)+ C”。 sizeof(char *)* ft_length(environ)+ 2'是没有意义的。 – melpomene

+2

'env [x] =(char *)malloc(sizeof(char)* 4); env [x] =“ccc \ 0”;'泄漏内存。它不会做你认为它做的事情,并且如果它*做了*,那么对于越界访问将是未定义的行为。 – EOF

+0

@melpomene哦,你是对的!我会尽快修复并重试。 – julien

回答

2
malloc(sizeof(char*) * ft_length(environ) + 2) 

如果需要阵列中的两个额外的元素,那会是

malloc(sizeof(char*) * (ft_length(environ) + 2)); 

或者使用calloc

calloc (ft_length(environ) + 2, sizeof(char*)); 

此外

env[x] = (char*)malloc(sizeof(char) * 4); 
env[x] = "ccc\0"; 

是另一个陷入每个人似乎落入。您指定一个指针值为env[x],然后立即后悔和分配另一个指针值,忘记第一个,创建一个内存泄漏的过程中,并使您的env无法free作为新的字符串不指向到动态分配的内存。这看起来是正确的(即使有很多冗余),它会让你感到特别莫名其妙。

env[x] = malloc(4); // sizeof(char) is always one; casting not needed 
        // also see below 
strcpy (env[x], "ccc"); // of course no `\0` is needed 

既然你有代码,可动态分配的字符串的副本在两个地方,你可能想使这个代码放到一个功能,或者使用现有的(尽管是非标准)功能strdup。这是特别重要的,因为没有好的方法来复制字符串,否则。

env[x] = malloc(4); 
strcpy (env[x], "ccc"); 

假定长度。如果文字会改变呢?

env[x] = malloc(strlen("ccc")+1);       
strcpy (env[x], "ccc"); 

如果某人更改了一个字面并忘记了另一个字面怎么办?

const char ccc[] = "ccc"; 
env[x] = malloc(sizeof(ccc)); 
strcpy (env[x], ccc); 

这可以工作,但你有一个额外的行声明一个变量。这听起来不像很多,但为什么?

env[x] = strdup("ccc"); 

看起来更好,保持更好。

如果你写你自己的strdup不这样做

out = (char*)malloc(sizeof(char) * strlen(in) + 1); 
bzero(out, strlen(in)); 
strncpy(out, in, strlen(in)); 

而是

out = malloc(strlen(in) + 1); 
strcpy(out, in); 

bzero是多余的,因为它会零出正是strcpy将与非零覆盖字节值在下一行。 strncpy + strlen组合是明显错误,因为它不会空 - 终止目标字符串。 strncpy(out, in, strlen(in)+1)将是正确的,但是是多余的,因为它与简单的strcpy(out, in)完全相同。

+0

不应在对'malloc'的调用中假定字符串文字的长度。使用'strdup',或者实现你自己的'strdup',并且一致地使用它! – pat

+0

@pat你打我吧 –

+0

我认为你的意思是'malloc(strlen(“ccc”)+ 1)',而不是'malloc(“ccc”)'。 – pat