【问题标题】:My program is not deallocating space correctly我的程序没有正确分配空间
【发布时间】:2021-11-23 18:54:03
【问题描述】:

我这里有这段代码,用于标记字符串。此行检查字符串是否有引号并返回不带引号的字符串。如果我从用户那里得到一些东西,例如Hello "nice" day,它将返回hello nice day

char* str = take_quotes(line, stderr);

take_quotes 函数正在分配空间,所以我需要在我的 tokenize 函数中释放空间。

我认为在我使用这条线之后,我可以在归还我的令牌之前释放空间,但是当我这样做时,我会丢失我的令牌中的任何东西。我应该如何释放从take_quotes返回的空间?

char** tokenize(char* line){
    if(line == NULL)
        return NULL;

    char* str = take_quotes(line, stderr); //free space

    char **tokens = malloc( sizeof( char * ) );
    *tokens = NULL;
    size_t n = 1;

    const char *delim = " \t \n";

    char *p = strtok( str, delim );

    int success = p != NULL;

    while ( success )
    {
        char **tmp = realloc( tokens, ( n + 1 ) * sizeof( char * ) );

        if ( tmp == NULL )
        {
            free( tokens );
            tokens = NULL;

            success = 0;
        }
        else
        {
            tokens = tmp;

            tokens[n - 1] = p;
            tokens[n] = NULL;
            ++n;

            p = strtok( NULL, delim );

            success = p != NULL;
        }
    }

    free(str);
    str = NULL;

    return tokens;
}

当我换行时

tokens[n - 1] = p;

tokens[n - 1] = strdup(p);

我在 Valgrind 中遇到了很多错误

==8175== LEAK SUMMARY:
==8175==    definitely lost: 12 bytes in 3 blocks
==8175==    indirectly lost: 0 bytes in 0 blocks
==8175==      possibly lost: 6 bytes in 1 blocks
==8175==    still reachable: 0 bytes in 0 blocks
==8175==         suppressed: 0 bytes in 0 blocks
==8175== 
==8175== For lists of detected and suppressed errors, rerun with: -s
==8175== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)

【问题讨论】:

  • tokens[n - 1] = p:不是将指针分配给将被释放的缓冲区,而是复制字符串。你可以使用strdup(3) 或其他东西来做到这一点。

标签: c malloc tokenize


【解决方案1】:

strtok 通过在分隔符处将 NUL 终止字节插入到字符串中,就地标记给定的字符串。没有分配额外的内存。当您释放str 时,您正在破坏包含这些令牌的内存。

一种方法是复制您的令牌,并在此过程中为每个令牌分配内存。

strdup 可用于此目的:

tokens[n - 1] = strdup(p);

如果strdup 在您的系统上不可用,那么您将不得不重写它的功能(提示:strlen + malloc + strcpy,并且不要忘记为 NUL 终止字节提供额外空间! )。

当需要释放 tokens 时,您必须首先释放它包含的每个单独元素。


释放锯齿状数组的每个元素的人为示例:

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

void free_tokens(char **tokens) {
    for (char **t = tokens; *t != NULL; t++)
        free(*t);

    free(tokens);
}

int main(void) {
    char **tokens = malloc(3 * sizeof *tokens);
    tokens[0] = strdup("hello");
    tokens[1] = strdup("world");
    tokens[2] = NULL;

    for (char **t = tokens; *t != NULL; t++)
        printf("token:[%s]\n", *t);

    free_tokens(tokens);
}

【讨论】:

  • 感谢您的帮助。我只是用使用 strdup 时发生的情况来编辑我的问题。我之前尝试过使用,但它使我的程序出现更多错误。也许是因为我不知道如何做你提到的最后一部分,“释放令牌时它需要是个人的”。你能进一步解释一下吗?
  • @p20xx 我已经更新了答案以包含一个释放这种数据结构的示例。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多