看看这个:
char (*options)[MAXLEN];
char *ptr;
ptr = strtok(input, " \r\n");
if(!ptr)
continue;
int i = 0;
optionen = malloc(sizeof(*options));
if(!options)
die("malloc");
while(ptr){
if(i > 0){
options = realloc(options, (i+1)*sizeof(*options));
if(!options)
die("malloc");
}
strcpy(options[i], ptr);
if(!options[i])
die("strcpy");
ptr = strtok(NULL, " \r\n");
i++;
}
/*create another entry options[i] that is a nullpointer*/
目的是 exec(3) 命令需要一个空指针作为 *options[] 数组的最后一个条目才能正常工作。
问题:如何向数组中添加另一个条目,该条目是一个 NULL - 指针?我知道我不能分配另一个 options[i]
并将其设置为 NULL
因为 stackoverflow 上的一些人告诉我永远不要这样做(内存泄漏)。
注意:输入是一些包含一些命令行的数组 - input(char input[MAXLEN];
) 和 die()
只是调用 perror()
然后 exit()
最佳答案
无论谁告诉您“不能分配另一个 options[i]
并将其设置为 NULL”都是错误的。这正是您所做的。
但是,您的代码中存在错误,这些错误表明您不理解“分配另一个选项[i]
”的含义。
char (*options)[MAXLEN]; /* This is wrong */
char *ptr;
ptr = strtok(input, " \r\n");
if(!ptr)
continue;
int i = 0;
optionen = malloc(sizeof(*options));
if(!options)
die("malloc");
while(ptr){
if(i > 0){
options = realloc(options, (i+1)*sizeof(*options));
if(!options)
die("malloc");
}
strcpy(options[i], ptr); /* This is also wrong */
if(!options[i])
die("strcpy");
ptr = strtok(NULL, " \r\n");
i++;
}
首先,char (*options)[MAXLEN]
是错误的数组类型,其中的条目不能 设置为 NULL。您需要的是 char **options
。
其次,您已经在执行的 realloc
操作实际上是分配更多的 options[i]
插槽。但是您还需要为字符串本身分配空间(但不是 为NULL)。您可以使用 strdup
来做到这一点。
options[i] = strdup(ptr); /* Instead of the "also wrong" line */
(根据 input
是什么,您也许可以仅使用 strtok
返回的字符串指针来摆脱困境,但如果没有看到更多您的代码,我可以'不确定那是安全的。)
然后,在循环之后,您只需将最后的 options[i]
槽设置为 NULL 即可。
我会以不同的方式构造循环,如下所示:
char **options;
char *ptr;
size_t i, asize;
ptr = strtok(input, " \t\r\n");
if (!ptr) continue;
options = 0;
i = 0;
asize = 2;
do {
while (i >= asize) {
asize *= 2;
options = xreallocarray(options, asize, sizeof(char *));
}
options[i++] = xstrdup(ptr);
ptr = strtok(0, " \t\r\n");
} while (ptr);
while (i >= asize) {
asize *= 2;
options = xreallocarray(options, asize, sizeof(char *));
}
options[i] = 0;
execve(options[0], options, environ);
die("execve");
函数 xreallocarray
和 xstrdup
是非标准函数,但它们应该包含在您编写的每个程序中的简单函数包中。这是他们的定义。他们使用您已有的 die() 函数。
void *
xreallocarray(void *optr, size_t nmemb, size_t size)
{
/* s1*s2 <= SIZE_MAX if both s1 < K and s2 < K where K = sqrt(SIZE_MAX+1) */
const size_t MUL_NO_OVERFLOW = ((size_t)1) << (sizeof(size_t) * 4);
if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
nmemb > 0 && SIZE_MAX / nmemb < size) {
errno = ENOMEM;
die("malloc");
}
void *rv = realloc(optr, size * nmemb);
if (!rv)
die("malloc");
return rv;
}
char *
xstrdup(const char *s)
{
size_t n = strlen(s) + 1;
char *rv = malloc(n);
if (!rv)
die("malloc");
memcpy(rv, s, n);
return rv;
}
关于创建一个关于内存泄漏的安全空指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41089931/