创建一个关于内存泄漏的安全空指针

标签 c arrays null-pointer

看看这个:

    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");

函数 xreallocarrayxstrdup 是非标准函数,但它们应该包含在您编写的每个程序中的简单函数包中。这是他们的定义。他们使用您已有的 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/

相关文章:

java - try/catch vs if/else 抛出 NullPointerException

c - 动态数组调整大小混淆双重释放或损坏错误

mysql - 在 Swift 中使用 array.append() 向数组添加值时出现问题

c - 'fopen' 返回 NULL 文件指针,即使文件是使用 C 创建的

Javascript:将对象从一个数组移动到另一个数组:最佳方法?

arrays - Swift 字符串数组一直显示为空

c++ - 删除 NULL 指针是否安全?

c - 将 csv 文件中的浮点值写入新文件并迭代字段

c++ - 负的 dwLowDateTime 在 FILETIME 结构中意味着什么?

c - C语言中的“const”可能是多余的?