访问在指向strtok的字符数组的指针中传递的变量时获取不正确的值

Ada*_*ate 5 c arrays pointers strtok

这是我的代码

//Split up the config by lines
int x;
int numberOfConfigLines = 0;
for (x = 0; x < strlen(buffer); x++)
{
    if (buffer[x] == '\n') {
        numberOfConfigLines++;
    }
}
char *configLines[numberOfConfigLines];
tokenize(configLines, buffer, "\n", numberOfConfigLines);
Run Code Online (Sandbox Code Playgroud)

这个函数的想法是计算缓冲区中的换行量,然后使用以下命令将缓冲区拆分为strtok数组:

#include <string.h>
#include <stdlib.h>

void tokenize(char **arrToStoreTokens, char *delimitedString, char *delimiter, int expectedTokenArraySize) {
    //Create a clone of the original string to prevent making permanent changes to it
    char *tempString = (char *)malloc(strlen(delimitedString) + 1);
    strcpy(tempString, delimitedString);

    if (expectedTokenArraySize >= 1) {
    arrToStoreTokens[0] = strtok(tempString, delimiter);

        int x;
        for (x = 1; x < expectedTokenArraySize; x++ ) {
            arrToStoreTokens[x] = strtok(NULL, delimiter);
        }
    }

    //Dispose of temporary clone
    free(tempString); 
}
Run Code Online (Sandbox Code Playgroud)

如果我访问arrToStoreTokens[0]直接,我得到正确的结果,但是当我尝试访问configLines[0]一次的tokenize功能已经结束,我得到不同的结果(可以是未知字符或干脆为空)

另外,我相信只有在我开始以root身份运行程序时才开始发生这种情况(针对不同的要求) - 尽管我可能错了. - 编辑:确认不是问题.

有任何想法吗?

Ara*_*hor 4

strtok不会重新分配任何东西。它只会对您所提供的内容进行剪切和指示。

您的数组存储 strtok 为您提供的指针,但不复制内容。

因此,如果释放tempString变量,则释放 strtok 返回值所指向的数据。您必须保留它并仅在最后释放它。

或者,您可以对 strtok 的每个返回创建一个strdup,将其存储在数组中,以制作每个令牌的真实副本,但在这种情况下,您必须在最后释放每个令牌。

第二个解决方案如下所示:

void tokenize(char **arrToStoreTokens, char *delimitedString, char *delimiter, int expectedTokenArraySize) {
    //Create a clone of the original string to prevent making permanent changes to it
    char *tempString = (char *)malloc(strlen(delimitedString) + 1);
    strcpy(tempString, delimitedString);

    if (expectedTokenArraySize >= 1) {
    arrToStoreTokens[0] = strdup(strtok(tempString, delimiter)); // Here is the new part : strdup

        int x;
        for (x = 1; x < expectedTokenArraySize; x++ ) {
            arrToStoreTokens[x] = strdup(strtok(NULL, delimiter)); // Here is the new part : strdup
        }
    }

    //Dispose of temporary clone
    free(tempString); 
}
Run Code Online (Sandbox Code Playgroud)

使用该数组后,您必须使用如下函数删除它:

void deleteTokens(char **arrToStoreTokens, int arraySize)
{
    int x;
    for (x = 0; x < arraySize; ++x)
    {
        free(arrToStoreTokens[x]);
    }
}
Run Code Online (Sandbox Code Playgroud)