【问题标题】:C reverse string with dynamic memory具有动态内存的 C 反向字符串
【发布时间】:2021-09-12 04:20:03
【问题描述】:
#include <stdio.h>
#include <stdlib.h>

char* ch_reversed(const char* const str);
size_t ch_length(const char* const str);

int main()
{
    char* str = "merhaba";
    
    printf("%s", ch_reversed(str));
    
    return 0;
}

char* ch_reversed(const char* const str)
{
    if (!ch_length(str))
        return NULL;

    char* temp = malloc(ch_length(str) + 1);
    size_t length = ch_length(str);

    for (size_t i = 0; i < length; i++)
        temp[i] = str[length - i - 1];

    temp[length] = '\0';

    return temp;
}

size_t ch_length(const char* const str)
{
    size_t length = 0;

    while (str[length++]) {}
    
    return length - 1;
}
  • 在该代码中,我为反转字符串分配了内存,在主函数中,我直接将ch_reversed 函数传递给printf。但这是否会导致内存泄漏,因为我无法使用这种类型的用法释放内存?如果是这样,我可以将返回值分配给变量并使用该变量并用它释放内存,但我不想这样做。我希望能够像在这里一样直接使用该功能。那我该怎么办?

  • 对于这种情况,将字符串作为const char* const 传递是否合适,因为我无论如何都不会更改参数?或者我应该以const char* 或其他方式传递它?

  • 最后,有什么不好的地方要改吗?

【问题讨论】:

  • 是的,你有一个泄漏——你必须从ch_reversed() 捕获返回值并在退出之前释放它以避免泄漏。另一种方法是接受泄漏,或者将预先分配的缓冲区(及其长度)传递给函数(以及要反转的字符串)。 const char *const char * const 都可以;只使用const char * 更为常见,因为指针本身是否改变并不重要——它只是来自main() 程序(调用函数)的变量的副本。你写的没问题。
  • 未正确处理空字符串。在这种情况下,它应该返回一个空字符串,即一个指向空字符的指针。相反,它返回一个NULL 指针。您应该能够打印空字符串,但尝试打印NULL 指针会导致段错误。根本不需要对空字符串进行特殊处理。只需删除整个检查,(1)您将修复错误,并且(2)您的代码会更小。
  • 另外,const char* const str 声明并没有真正的意义。他们应该是const char *str。关键是指针的目标是恒定的。没有人关心指针本身。例如,查看手册页中的 strcpy 之类的内容,看看它们是如何声明其字符串参数的。
  • 顺便说一句,为给定的非空字符串调用ch_length() 三次似乎有点过分——一次就足够了。保存第一次(唯一)调用的长度并在后续行中使用它。鉴于您在其他地方大量使用const,令人惊讶的是您没有在char* str = "merhaba"; 中使用const
  • 顺便说一句,有什么理由使用您自己的 strlen() 实现?我使用了 C 实现,其中 strlen 进行了高度优化,运行速度比原始代码快很多倍,例如通过同时检查 8 或 16 个字节的 nul 字符。

标签: c string function pointers memory-leaks


【解决方案1】:

但这是否会导致内存泄漏,因为我无法释放内存 这种用法?

Valgrind 是检查内存错误的好工具。我通过 valgrind 运行了您的代码,结果如下:

==174== HEAP SUMMARY:
==174==     in use at exit: 8 bytes in 1 blocks
==174==   total heap usage: 2 allocs, 1 frees, 520 bytes allocated
==174==
==174== 8 bytes in 1 blocks are definitely lost in loss record 1 of 1
==174==    at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==174==    by 0x1091E6: ch_reversed (main.c:22)
==174==    by 0x10918B: main (main.c:11)
==174==
==174== LEAK SUMMARY:
==174==    definitely lost: 8 bytes in 1 blocks
==174==    indirectly lost: 0 bytes in 0 blocks
==174==      possibly lost: 0 bytes in 0 blocks
==174==    still reachable: 0 bytes in 0 blocks
==174==         suppressed: 0 bytes in 0 blocks
==174==

所以是的,你肯定是在泄漏内存。没有办法以调用函数的方式实际不泄漏内存。因此,您没有将结果分配给任何变量,因此您不能free()。我不明白您为什么不想只分配结果并稍后致电free()

我希望能够像在这里一样直接使用该功能。所以呢 我应该怎么做?

您可以立即调用它,只需将指针传递给printf()

int main(void)
{
    char *str = ch_reversed("merhaba");

    printf("%s", str);

    free(str);

    return 0;
}

您当然可以改用数组并对其进行修改:

char* ch_reversed(char* str) /* argument changed, as we want to modify the content of the array */
{
    size_t length = ch_length(str); /* no need for multiple function calls */

    if (!length)
    return NULL;

    char* temp = malloc(length + 1);

    strcpy(temp, str); /* copy original string to temp */ 

    for (size_t i = 0; i < length; i++)
      str[i] = temp[length - i - 1];

    free(temp); /* free temp */

    return str;
}

您的main() 函数应该如下所示,

int main(void)
{
    char str[] = "hello";

    printf("%s", ch_reversed(str)); /* this will alter str though */

    return 0;
}

是否适合将此字符串作为 const char* const 传递 情况,因为我无论如何都没有改变参数?

这样做是合法的,如果您不打算执行任何指针算术 - 修改或操作字符串。

最后,有什么不好的地方要改吗?

这个问题可能更适合Code Review

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-05-15
    • 2017-07-24
    • 2013-07-23
    • 1970-01-01
    • 1970-01-01
    • 2017-03-16
    相关资源
    最近更新 更多