2008-10-06 44 views
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,但我只是对此感到好奇。

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

回答

8

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

+2

修改它是非法的。这真的是一个const char *。 – 2008-10-06 16:01:30

+0

+1 const char *。 MemoryLeak :: s应该是const,它应该是const char * MemoryLeak :: retrieve() – quamrana 2008-10-06 17:20:39

0

也许坠机的原因是你没有0-终止字符串?

+0

Erm,字符串文字总是以null结尾。 – 2008-10-06 09:49:52

6

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

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

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

1

谢谢科迪和理查德。

我发现了错误的原因。这是因为我正在删除已经删除的对象。我在做:

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 :: string被自动初始化为空字符串。分配的任何内存都会正确解除分配。它可以很容易地作为可修改和不可修改的版本返回。操作也很容易(,即增长收缩变化)。如果你增加一个C字符串,你需要重新分配内存并将字符串复制到新的内存中(这很容易导致错误)。

为了应对动态分配你的对象,我会了解智能指针。
有关智能指针的更多详细信息,请参阅此文章。
Smart Pointers or who owns you Baby

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. 
相关问题