gpt4 book ai didi

C - 将最后一个设置为 NULL 时数组值消失

转载 作者:太空宇宙 更新时间:2023-11-03 23:20:00 25 4
gpt4 key购买 nike

我在使用(相当大的)c 程序时遇到了一个小问题,我发现问题不是来 self 的程序本身,而是我创建数组的方式。

我的问题如下,我需要创建一个与包含环境变量 (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] 最后是空的,当我将最后一个数组值设置为 NULL (env[++x] = NULL)。但是,好吧,如果我想在没有段错误的情况下打印我的数组,我需要这个为 NULL

所以,首先我想知道我的代码是否有错误?

我也尝试在我的 Linux 计算机(Ubuntu 16.04)上运行这段代码,似乎没有问题。

最佳答案

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 组合是明显错误,因为它不会以 null 终止目标字符串。 strncpy(out, in, strlen(in)+1) 是正确但多余的,因为它与普通 strcpy(out, in) 的作用完全相同。

关于C - 将最后一个设置为 NULL 时数组值消失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42599601/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com