连续重新分配字符字符串会导致内存泄漏吗?

4
我有两个问题:
Q1. 字符指针用于指向存储给定字符串的位置。如果我们不断重新分配字符串,是否会导致内存泄漏?
在Linux系统上,我看到:
$ cat chk.c
#include <stdio.h>

#define VP (void *)

int main()
{
        char *str;

        str = "ABC";
        printf("str = %p points to %s\n", VP str, str);

        str = "CBA";
        printf("str = %p points to %s\n", VP str, str);

        return 0;
}

$ cc chk.c && ./a.out
str = 0x8048490 points to ABC
str = 0x80484ab points to CBA
$

问题2. 可以分配的字符串的最大长度是多少?

4个回答

2

你的示例代码会出现内存泄漏吗? 不会。 因为你已经在程序中分配了常量字符串,所以不会发生额外的内存分配。

内存泄漏来自于忘记使用malloc()等调用,或者调用那些可能不知道内部进行malloc()类型操作的函数。要注意返回指向内存的指针的函数,例如strdup()。这些函数往往不是线程安全的,或者会泄漏内存,有时两者都会出现。更好的选择是像snprintf()这样的函数,其中调用方提供了内存缓冲区和最大大小。这些函数不会泄漏内存。

最大字符串长度:通常没有人工限制,除了可用内存。堆栈内存可能受到各种限制的影响(char can_be_too_big[1_000_000]),但是从malloc()获得的内存则没有。malloc内存的问题在于你有多少可用内存(char * ok = malloc(1_000_000))。理论上,您的本地size_t提供了要分配的最大内存,但实际上它要小得多。


1

只有在使用malloc/realloc/calloc分配内存并忘记free时才会出现内存泄漏。在上面的例子中,我们没有手动分配内存,所以我认为没有内存泄漏。


谢谢Mahesh。你能指出一些关于释放字符指针相关的更多信息的来源吗? - Quiescent

1

好的,更具体地说,通常发生的情况是(特定于操作系统,但据我所知,这是普遍的,可能在某个规范中)在可执行文件的指令集中嵌入了字符串“ABC”和“CBA” - 这些字符串嵌入在程序本身中。当你执行str="ABC"时,你的意思是,“我希望这个字符串指针指向包含字符串ABC的编译程序中的地址”。这就是为什么在运行时存在“字符串”和“字符串字面量”的区别,如果你在文档中看到的话。由于你没有为字面量分配空间 - 编译器将其嵌入了你的程序中 - 你不必为其释放空间。

无论如何,当你的进程被卸载时,操作系统会自然地释放这个资源作为卸载程序的副作用。实际上,一般来说,在程序退出后泄漏是不可能的,因为操作系统会在程序退出时回收任何你忘记回收的资源,即使是极其严重的泄漏。(这并不完全正确 - 如果你做链接库的事情,你可以导致另一个未卸载的程序泄漏 - 但它已经足够接近了)。这只是操作系统照顾的一些事情。


真的是一篇很好的解释。除了原帖作者,它也对我有所帮助...在系统软件中,我正在读取字面量,并且您在这里提到了字符串字面量。这两个概念是相同的吗? - Muthu Ganapathy Nathan
在软件中,字面值(literal)通常指硬编码的数据 - 因此您也可以有整数字面值,例如 `int num; num = 20" : 20 就是字面值。我不确定您具体在做什么,但我不确定是否存在字面值的严格数学定义:如果使用动态语言怎么办?数字或字符串从未在任何地方被“编译” - 它更像是代码固有的一块数据概念,而不是从外部源读取的。 - Matt

0
当你为指针p分配内存时,如果没有释放该内存或没有使其他指针指向该内存,而改变了p的值,则会发生内存泄漏。

(E.g)

char* p =  malloc(sizeof(char)*n);
char* q= "ABC";

如果你执行以下操作:

p=q;

那么就会出现内存泄漏的问题。 如果你不使用内存分配,就不会有任何内存泄漏。

而且:

char* q= "ABC";

在该语句中,q将自动指向一个常量位置。因此,q的值无法修改。 (例如)

char* q = "ABC";
q[1] = 'b';

这些语句将导致分段错误。

更多参考:

修改值时的错误

动态内存分配


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接