函数内部的字符串文字:自动变量或在堆中分配的
String literals inside functions: automatic variables or allocated in heap?
我们在函数内部使用的字符串文字是自动变量吗?或者它们是在堆中分配的,我们必须手动释放?
我遇到了如下代码所示的情况,我将一个字符串文本分配给类的一个私有字段(在代码中标记为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.
- 何时在函数中声明堆栈分配变量?
- 取消引用指针并立即为其分配变量,导致分段错误
- 在C++中动态分配变量类型
- 在函数 (c++) 中分配变量类型和大小数组
- 无法在命名空间范围内分配变量
- 自我分配变量的定义
- 在 CUDA C++中分配变量 - 无法分配设备变量
- 在 CPP 中动态分配变量的数据类型
- 为什么无法在类主体中分配变量?
- const 类方法是否阻止在类外部分配变量?
- 从文件中分配变量,并使用定界符分配
- 分配指针后,是否可以为指针指向的事物分配变量名称?
- 读取外部文件并在类似xml的输入中分配变量
- 有没有办法在不分配变量的情况下将字符串连接到数字
- 如果使用alloca在内联函数中的堆栈上分配变量,那么在内联函数返回后,其引用是否有效
- 堆分配变量的结构成员对齐
- 包含溢出缓冲区的堆栈分配变量,也称为缓冲区
- 在 GetTransfer 之后,我在帐户 1 收到未分配变量错误。我无法弄清楚我搞砸了什么逻辑错误
- 对动态分配的变量的引用与指向相同动态分配变量的指针
- 在C++中为用户输入分配变量