C - 将最后一个设置为NULL

时间:2017-03-04 18:19:43

标签: c malloc environment-variables

我对一个(非常大的)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)上运行此代码,似乎没有问题。

1 个答案:

答案 0 :(得分:2)

result = pd.Series(result)

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

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)完全相同。