3

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

我的情况类似于下面显示的代码,其中我将字符串文字分配给类的私有字段(在代码中标记为 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,但我只是对此感到好奇。

一如既往,非常感谢任何指针或帮助:) 谢谢。

4

5 回答 5

9

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

于 2008-10-06T09:31:29.937 回答
6

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

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

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

于 2008-10-06T09:49:58.167 回答
1

谢谢科迪和理查德。

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

if (obj != NULL) delete obj;

我将其更改为:

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

学习 C++ 绝对很有趣 :)

于 2008-10-06T10:30:07.383 回答
0

也许崩溃的原因是你没有 0 终止字符串?

于 2008-10-06T09:48:23.177 回答
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-Strings。这些不应与 C++ std::string 混淆。C++ std::string 自动初始化为空字符串。任何分配的内存都被正确地取消分配。它可以很容易地作为可修改和不可修改的版本返回。它也很容易操纵(增长收缩变化)。如果你增加了一个 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.
于 2008-10-06T16:20:25.023 回答