函数内部的字符串文字:自动变量或在堆中分配的

String literals inside functions: automatic variables or allocated in heap?

本文关键字:分配 变量 字符串 内部 文字 函数      更新时间:2023-10-16

我们在函数内部使用的字符串文字是自动变量吗?或者它们是在堆中分配的,我们必须手动释放?

我遇到了如下代码所示的情况,我将一个字符串文本分配给类的一个私有字段(在代码中标记为ONE),并在稍后的程序中检索它并使用它(标记为TWO)。我是否将堆栈中的变量分配给ONE中的字段?代码是否可以引用一个悬空指针,在这种情况下,该指针之所以有效,是因为程序足够小?

我已经编译并运行了它,它运行得很好,但我在实际的程序中遇到了一个奇怪的崩溃,我将字符串文本分配给类的字段,我怀疑上面提到的情况。

#include <iostream>
using namespace std;
class MemoryLeak
{
private:
    char *s;
public:
    MemoryLeak() {}
    void store()
    {
        s = "Storing a string"; // ONE
    }
    char *retrieve()
    {
        return s;
    }
};
int main()
{
    MemoryLeak *obj = new MemoryLeak();
    obj->store();
    cout << obj->retrieve() << endl; // TWO
    delete obj;
    return 0;
}

我应该将变量"s"声明为char数组而不是指针吗?我计划使用std::string,但我只是对此感到好奇。

如有任何建议或帮助,我们将一如既往地不胜感激:)谢谢。

字符串文字将由编译器放置在二进制文件的初始化数据或文本(代码)段中,而不是驻留在(运行时分配的)内存或堆栈中。因此,您应该使用指针,因为您将引用编译器已经为您生成的字符串文字。请注意,修改它(通常需要更改内存保护)将更改此文字的所有用途。

修改字符串文字是未定义的行为,很可能是程序崩溃的原因(ISO C++:2.13.4/2)。为了与C向后兼容,该标准允许从字符串文字转换为char*,只有在绝对需要的情况下,才应在代码中进行转换。

如果希望将字符串文本视为常量,则可以将成员的类型更改为const char *

如果您的设计要求可以修改s,那么我建议将其类型更改为std::string

谢谢Cody和Richard。

我找到了这个错误的原因。这是因为我正在删除一个已经被删除的对象。我在做:

if (obj != NULL) delete obj;

我把它改成:

if (obj != NULL)
{
    delete obj;
    obj = NULL;
}

学习C++肯定很有趣:)

可能崩溃的原因是您没有0-终止字符串?

让我们看看您的选项
还有几件事你应该做:

    /*
     * Should initialize s to NULL or a valid string in constructor */
        MemoryLeak()
        {
            store();
        }
        void store()
        {
            // This does not need to be freed because it is a string literal
            // generated by the compiler.
            s = "Storing a string"; // ONE
            // Note this is allowed for backward compatibility but the string is
            // really stored as a const char* and thus unmodifiable. If somebody
            // retrieves this C-String and tries to change any of the contents the
            // code could potentially crash as this is UNDEFINED Behavior.
            // The following does need to be free'd.
            // But given the type of s is char* this is more correct.
            s = strdup("Storing a string");
            // This makes a copy of the string on the heap.
            // Because you allocated the memory it is modifiable by anybody
            // retrieving it but you also need to explicitly de-allocate it
            // with free()
        }

你正在做的是使用C字符串。这些不应该与C++std::string混淆。C++std::字符串会自动初始化为空字符串。任何已分配的内存都会被正确地取消分配。它可以很容易地作为可修改和不可修改的版本返回。它也很容易操作(生长收缩变化)。如果你增加了一个C字符串,你需要重新分配内存,并将字符串复制到新的内存等(这非常耗时,很容易出错)。

为了处理动态分配对象的问题,我将学习智能指针
有关智能指针的更多详细信息,请参阅本文
智能指针或谁拥有你宝贝

std::auto_ptr<MemoryLeak> obj(new MemoryLeak());
obj->store();
std::cout << obj->retrieve() << std::endl; // TWO
// No need to delete When object goes out of scope it auto deletes the memory.