在数组中设置 NULL 的奇怪行为

Strange behavior by setting NULL in array

当我尝试在 c 中的字符串数组(char 数组)的末尾设置 NULL 值时,我有一个奇怪的行为。我需要将参数传递给带有 execv 的进程,并且我的所有参数都是 int 类型,所以我试图获取一个字符串数组,所有参数都转换为 char 数组。我创建了一个 returns 这个字符串数组的函数,但是当我将数组的最后一个值设置为 NULL(在参数中有一个终止值)时,我丢失了存储在第二个位置的值。如果我删除 NULL 值,则不会发生任何问题。这是代码,希望有人能帮助我

char **getParams(int offset, short isNode, int first) {

    printf("Get params\n");

    int args = 8;
    int totalSize = 0;
    int tmp[args];

    tmp[0] = sizeof(char) * 5; // user / node
    tmp[1] = snprintf(NULL, 0, "%d", x);
    tmp[2] = snprintf(NULL, 0, "%d", x2);
    tmp[3] = snprintf(NULL, 0, "%d", x3);
    tmp[4] = snprintf(NULL, 0, "%d", x4);
    tmp[5] = snprintf(NULL, 0, "%d", x5);
    tmp[6] = snprintf(NULL, 0, "%d", x6);
    tmp[7] = snprintf(NULL, 0, "%d", x7);

    int i = 0;
    for (i = 0; i < args; i++) totalSize += tmp[i];

    char **_pars = malloc(totalSize + sizeof(NULL));
    
    i = 0;
    for (i = 0; i < args; i++) _pars[i] = malloc(tmp[i]);
    
    _pars[0] = isNode == 1 ? "aaaa" : "bbbb" ;
    sprintf(_pars[1], "%d", x);
    sprintf(_pars[2], "%d", x2);
    sprintf(_pars[3], "%d", x3);
    sprintf(_pars[4], "%d", x4);
    sprintf(_pars[5], "%d", x5);
    sprintf(_pars[6], "%d", x6);
    sprintf(_pars[7], "%d", x7);
    printf("Value: %s", _pars[1]); /// Print without problem value
    _pars[8] = NULL;   //// ,--- Here happens the issue
    printf("Value: %s", _pars[1]); /// Doesnt print any value

    return _pars;
}

我也试过把它放在我 malloc 数组位置的 for 之后,但没有结果

_pars[8] = malloc(sizeof(NULL));

_pars 被假定为指向 char 的指针数组,这意味着

_pars = malloc(args * sizeof(char*));

但是你为字符串分配了内存,指针应该指向。

你所有的分配都是错误的。

首先你要创建一个包含8个元素的数组,所以第一个分配应该是

char **_pars = malloc(8 * sizeof *_pars);

或者,如果您希望数组由空指针终止,您需要分配 9 个元素(将 8 换成上面的 9)。

其次,snprintf 返回的大小 包含空终止符,因此您的所有调用

_pars[i] = malloc(tmp[i]);

应该是

_pars[i] = malloc(tmp[i] + 1);

以适应空终止符。


另一方面,如果将所有 x 值放在一个数组中,则所有代码都可以大大简化:

int exes[8] = { x, x2, x3, x4, x5, x6, x7 };

因为这样你就可以对所有重复代码使用循环:

for (unsigned i = 1; i < 8; ++i)
{
    tmp[i] = snprintf(NULL, 0, "%d", exes[i]);
}