簡體   English   中英

如何在C中為字符串數組動態分配內存?

[英]How do I dynamically allocate memory for an array of strings in C?

我閱讀了有關C語言中動態數組的先前問題,但是無法將答案與我的問題聯系起來。

我正在使用fgets從stdin獲取命令,刪除了換行符,然后希望將每個由空格分隔的命令存儲在動態分配的字符串數組中。 但是我在分配和重新分配內存的正確方法上遇到了很多麻煩。 我正在使用clang編譯,並不斷出現分段錯誤11。然后,我使用了-fsanitize=address並不斷得到:

== 2286 ==錯誤:AddressSanitizer:pc 0x000108fb6f85 bp處地址0x60200000eeb8上的堆緩沖區溢出0x7fff56c49560 sp 0x7fff56c49558在0x60200000eeb8線程T0上寫入大小8

這是我的代碼:

// Sets a delimiter to split the input
const char *seperator = " ";

char *token = strtok(line, seperator);

char **cmds = (char **) malloc(sizeof(char) * sizeof(*cmds));
// Adds first token to array of delimited commands
cmds[0] = token;

int count = 1;
while (token != NULL) {
    token = strtok(NULL, sep);
    if (token != NULL) {
        cmds = (char **) realloc(cmds, sizeof(char) * (count + 1));
        // Adds next token array of delimited commands
        cmds[count] = token;
        count++;
    }
}

您沒有分配足夠的內存。 cmds是一個指針數組,因此每個元素都是sizeof(char *)字節,而不是sizeof(char)字節。

在初始分配中,您需要1個char * ,然后在后續分配中,您需要count + 1

另外, 不要malloc的返回值 ,因為這會隱藏其他問題,並且不要忘記檢查失敗。

char **cmds = malloc(sizeof(char *) * 1);
if (cmds == NULL) {
    perror("malloc failed");
    exit(1);
}
...
        cmds = realloc(cmds, sizeof(char *) * (count + 1));
        if (cmds == NULL) {
            perror("reallocfailed");
            exit(1);
        }

首先,根據定義, sizeof(char)始終為1。 而且編碼不會使您的代碼更具可讀性。

但是指向char的指針需要sizeof(char*)個字節(取決於機器和ABI ,通常為8或4個字節)。 如果使用GCC,我至少建議使用gcc -Wall -Wextra -g編譯您的代碼。

最后,我發現您的代碼效率低下。 您正在每個循環調用realloc 我將維護一個包含分配大小的變量

 int allocsize = 4; // allocated size in number of elements
 char **cmds = malloc(allocsize*sizeof(char*));
 if (!cmds) { perror("malloc"); exit(EXIT_FAILURE); };

(順便說一句,請始終檢查 malloc的結果;它可能會失敗)。

並避免realloc -ing每一次,我會以幾何方式增長分配的大小,所以在循環中:

 if (count>=allocsize) {
    int newallocsize = (4*allocsize)/3+10;
    cmds = realloc (cmds, newallocsize*sizeof(char*));
    if (!cmds) { perror("realloc"); exit(EXIT_FAILURE); };
    allocsize = newallocsize;
 }

另外,也可以不使用三個變量: cmdscountallocsize ,而可以使用以靈活數組成員結尾的單個struct (並保持其分配和使用的大小)。

  • 第一個malloc是錯誤的。如果在分配之前用* cmd代替cmd,會得到什么?
  • 它還使用sizeof(char),這是錯誤的。

正確的方法是..

// strtok modifies the string. So use writable string
char line[80] = "Hello my name is anand";
char *token = strtok(line, sep);
int count = 0;
// Alloc array of char* for total number of tokens we have right now
char **cmds = (char **) malloc(sizeof(char*) * (count + 1));

while (token != NULL) 
{
    /**
     * Alloc memory for the actual token to be stored.. 
     * token returned by strtok is just reference to the existing string 
     * in 'line'
     */
    cmds[count] = malloc(sizeof(char) * ((strlen(token) + 1)));
    // Adds tokens to array of delimited commands
    strcpy(cmds[count], token);
    count++;

    token = strtok(NULL, sep);
    if (token != NULL) 
    {
        // resize array of tokens to store an extra token
        char ** newCmds = (char **) realloc(cmds, sizeof(char*) * (count + 1));
        // only if realloc was successful then use it.
        if (newCmds != NULL)
        {
             cmds = newCmds;
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM