【问题标题】:Does char* with text automatically reserves memory as if malloc is used?char* with text 是否会像使用 malloc 一样自动保留内存?
【发布时间】:2019-09-04 20:46:42
【问题描述】:
// Example program
#include <iostream>
#include <string>

using namespace std;

int main()
{
    char **p;
    p = (char **)malloc(100);
    p[0] = (char *)"Apple";      // or write *p, points to location of 'A'
    p[1] = (char *)"Banana";     // or write *(p+1), points to location of 'B'

    cout << *p << endl;          //Prints the first pointer 
}

在上面的代码中:

p[0] = (char *)"Apple"; 

似乎会自动保留内存。没有malloc。这是 C/C++ 标准还是特定于编译器的?

更新 1 我实际上对它在 C 和 C++ 中的表现很感兴趣。只是我没有为上面的代码安装C编译器,所以我使用了C++。

所以 p 是在指向 HEAP 中的内存块(数组)的 STACK 上分配的,其中每个元素都指向(是指针)指向 DATA 段中的文字?哇!

【问题讨论】:

  • string literals 是一个很好的起点,至少对于 C++ 而言。
  • 这不是 c 这是 c++。在 C++ 中,您不能将字符串文字转换为非 const char *
  • @Jean-FrançoisFabre 是的,您可以,就像 OP 在此示例中所做的那样。未定义的行为仅在您尝试修改它指向的数据时出现。
  • 您正在分配一个指向常量的指针数组。如果指向的字符串是动态的,事情就会变得更有趣。此外,很少有理由在 C++ 中进行这种类型的字符串存储。 (C 是另一回事。)
  • 这是 C++ 中未定义的行为,您可以使用 new 而不是 malloc

标签: c++ pointers pointer-to-pointer


【解决方案1】:

似乎会自动保留内存。没有malloc。

动态分配并不是在 C++ 中获取内存的唯一方法。

变量p 具有自动存储功能。字符串文字是具有静态存储的数组。具有自动、静态或线程本地存储的对象会自动销毁。所有变量都具有这三个存储持续时间之一。

自动对象在(最窄的周围)范围结束时销毁,静态对象在main 返回后销毁,线程本地对象在线程退出时销毁。

这是 C/C++ 标准还是特定于编译器的?

示例程序大部分是标准的,除了:

  • 您没有包含保证声明 malloc 的标头。
  • 您还没有在动态分配的内存中创建char* 对象,因此程序的行为在C++ 中技术上是未定义的。见 P.P.P.S.下面是如何解决这个问题。

附:使用指向 char 的非 const 指针指向字符串文字是非常不安全的。尝试通过这样的指针修改字面量在语法上是正确的,但程序的行为在运行时是未定义的。请改用const char*。方便的是,您可以摆脱一些显式转换。

附言在 C++ 中不推荐 C 风格的显式转换。请改用static_castconst_castreinterpret_cast 或它们的组合。

P.P.P.S.不建议在 C++ 中使用malloc。请改用 newnew[]... 甚至更好,请参阅下一点。

P.P.P.P.S.不建议使用指向动态内存的裸指针。在此处使用 RAII 容器(例如 std::vector)将是一个好主意。

P.P.P.P.P.S.您的示例程序泄漏了动态分配。这是避免裸拥有指针的原因之一。


所以 p 分配在指向 HEAP 中的内存块(数组)的 STACK 上,其中每个元素指向(是指针)到 DATA 段中的文字?

语言本身与堆栈和堆内存以及数据段等概念无关。这些是特定于您正在使用的系统上的语言实现的详细信息。

【讨论】:

    【解决方案2】:

    malloc 进行动态内存分配。这里有经典的 static 内存分配,其中字符串常量将分配在二进制文件的数据部分(如果我没记错的话)。编译器预先知道您需要多少字节,因此它只会在编译期间分配它。这与 malloc 不同,在 malloc 中,您可以请求在运行时计算且预先未知的任意数量的字节。

    与您以恒定长度声明的数组相同,但不使用 malloc

    【讨论】:

    • “如果我没记错的话”——你可能是——许多架构没有“数据部分”,或者根本没有任何部分。
    • 我明白了,数据段和栈不同。
    • @AntonAndreev 在完全不同的地址空间中也可能有多个数据“段”。例如,在哈佛架构(与 von Neumann 相比)上,文字字符串将存储在代码空间中,而名称不佳的 p 数组将驻留在许多可能的可写空间之一中。字符串文字可能不在同一个地址空间,甚至不在同一个物理设备上。
    • Same with arrays that you declare with constant length, without using malloc 不完全是。一个非常量的静态大小的数组仍将位于可写空间中,因为它......嗯,可写的。将其填充到代码段、代码空间或为您的特定平台调用的任何内容中是没有意义的。即使是char *s="asdfasd' 也可以修改,因为它不是const
    【解决方案3】:

    [这是 C 答案,因为该问题最初也被标记为 [c]。但它也主要适用于 C++。]

    当你说

    char *str = "text"
    

    或者,就像在您的代码中一样,

    p[0] = "Apple";
    

    编译器为这些字符串"test""Apple" 分配内存。但是,绝对不是malloc 被调用。特别是,存储这些字符串的内存不能保证是(并且现在通常不是)可写的。而且您不能将这些指针传递给freerealloc——因为,它们一开始并不是来自malloc

    这是 C(以及,通过扩展,C++)的一个长期存在的方面,自古以来在任何编译器下都是如此。

    【讨论】:

    • “以及,通过扩展,C++”,好吧,没有char *str = "text"; 在 C++ 中是非法的。
    猜你喜欢
    • 1970-01-01
    • 2019-08-13
    • 2014-06-07
    • 1970-01-01
    • 2020-07-10
    • 2011-08-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多