【问题标题】:What happens with memory when we reassign value to char pointer?当我们将值重新分配给 char 指针时,内存会发生什么?
【发布时间】:2019-12-14 13:40:04
【问题描述】:

我想知道当我们做这样的事情时,内存中会发生什么

  char *s;
  s = "Text";
  s = "Another Text";

如果我做对了,通过将字符串分配给 char 指针内存是动态分配的。所以根据我的理解赋值表达式

  s = "Text";

等于

  s = (char *) malloc(5); // "Text" + '\0'
  strcpy(s, "Text");

好吧,这样我们就可以轻松地释放内存了

  free(s);

但是...在将同一个指针重新分配给另一个值后,它会分配新的内存段来存储该值。

  s = "Text";
  printf("\n(%p) s = \"%s\"", s, s);

  s = "Another Text";
  printf("\n(%p) s = \"%s\"", s, s);

输出:

  (0x400614) s = "Text"
  (0x400628) s = "Another Text"

这意味着我们不能再访问旧值的地址,我们不能再释放它了。再次调用free(s); 可能只会释放该指针使用的最后一个内存段。

我的问题是:如果我们一遍又一遍地重新分配相同的 char 指针,它是否会在运行时消耗越来越多的程序内存,或者垃圾会以某种方式自动释放?

我希望这足以证明我的问题,想不出更好的例子。如果有什么不够清楚,请要求进一步澄清。

【问题讨论】:

  • 甚至没有关闭。语句序列s = "Text"; s = "Another Text"; 根本不涉及任何动态内存分配。 唯一需要显式释放的情况是在动态分配内存之后。在您讨论的情况下,没有动态分配内存,因此根本不需要释放。
  • @Peter 知道了。如果我们在运行时从文件中读取字符串并分配给指针而不是使用编译时存储的值怎么办?猜猜,在这种情况下需要动态分配,因为编译器无法知道我们将从文件中加载什么以及将消耗多少内存。
  • @Peter 在另一个想法上,甚至不可能从文件或标准输入读取字符串到 char * 指针,而没有以前的 malloc/calloc 指向该指针。
  • 不是这样。可以使用自动存储持续时间创建阵列。如果该数组作为参数传递给期望指针的函数,则该函数接收该数组第一个元素的地址。同样,不需要使用malloc() 和相关函数进行显式分配,也不需要使用free() 进行释放。您确实需要获得一篇不错的 C 介绍性文本,并花时间阅读它,而不是错误地猜测 C 中的工作原理。
  • @Peter,是的,你说得对。我真的必须阅读更多关于这个主题的内容。但是你在评论的第一部分失去了我。如果我猜错了malloc 需要从文件或标准输入中读取,请告诉我为什么我不能这样做char *s; fgets(s, 100, stdin);?在从标准输入读取之前,那段代码在没有 malloc 的情况下不起作用。使用fscanffread 从零char * 的文件中读取字符串时也会发生同样的情况。在编译器中试过,这次不是猜测。

标签: c memory-management memory-leaks


【解决方案1】:

你的理解是错误的。这只是分配,它不分配任何内存。在您的示例中,您为指针分配了字符串文字的地址。字符串字面量在编译时创建并放置在只读内存中

您现在可以通过分配指针来分配任何内存

【讨论】:

  • 哦,所以它们是在编译期间静态分配的,而不是在运行时?那样的话,我就不用担心释放它了吧?
  • Re“我不用担心释放它,对吧?”,你不能释放由字符串字面量创建的字符串。
  • @ikegami thanx,这是我需要的确认。
【解决方案2】:

这不等于做一个malloc。发生的事情是字符串文字存储在内存的只读部分中。并且分配的不是指针的分配。程序中的所有字符串字面量都是从一开始就分配好的。

值得一提的是,严格来说,它们并没有存储在只读内存中,但它们可能是并且写入字符串文字是未定义的行为。

您不能也不应该在字符串文字上调用 free。好吧,你可以,但程序可能会崩溃。

【讨论】:

  • 所以,字符串在编译时存储在某个地方,而赋值只会将内存中这些字符串的地址提供给指针,对吧?
  • @Wh1T3h4Ck5 是
【解决方案3】:
  • 如果不进行优化,编译器将为字符串文字“text1”和“text2”保留两个不同的内存空间。

  • 如果赋值行在您的问题中非常连续,并且如果在第一个赋值行之后没有执行任何操作(假设使用优化进行编译),编译器很可能不会为第一个字符串文字分配任何空间,也不会产生第一个赋值行的任何操作码。

【讨论】:

    猜你喜欢
    • 2016-10-16
    • 1970-01-01
    • 1970-01-01
    • 2012-01-05
    • 2020-03-04
    • 1970-01-01
    • 1970-01-01
    • 2018-11-25
    • 2014-12-20
    相关资源
    最近更新 更多