'new'的字符串分配问题

时间:2010-08-20 18:34:17

标签: c++ string memory-management

如有疑问,请转到Stackoverflow ...

我遇到字符串分配问题。我的目标是存储n个传递的引用字符串的长度。我检查m_p是否为null因为我认为在调试模式下MS喜欢将地址设置为0xcccccccc而不是0x00000000。

我把1分进了长度。但是当我使用new分配它时,我在m_p中得到大约15个符号字符。如果m_size = lenth + 1是2,那该怎么办?我希望它只分配两个单元格。如何将其限制为长度+ 1?

 String::String(const char *str, int length) {
 m_size = length + 1;  // make room for null-terminated string

 if (m_p != NULL)
  m_p = NULL;

 try
 { 
  m_p = new char[m_size]; 
 }
 catch (bad_alloc e)
 {
  throw e;
 }

 strncpy(m_p, str, m_size); 
}

8 个答案:

答案 0 :(得分:4)

让我指出这里的缺陷:

  • 您没有捕获异常处理的分配问题,请检查NULL的返回值。
  • 如果你知道源和目的地的大小,为什么要使用strncpy? memcpy是这里最快的选择。
  • 您的变量的初始值未定义,并且会根据平台和配置而有所不同。不要担心之前的m_p,只需赋值。
  • m_p是一个可怕的名字。它没有说它是什么! m_pString至少?
  • 抓住异常并重新抛出它?为什么?
  • 你没有终止字符串。这是主要问题。您的源字符串是否已终止?你似乎最终得到了一个未终止的字符串。
  • 正如所指出的那样,有一些随时可用的STL课程可以为您完成所有工作并且已经使用了几十年。

答案 1 :(得分:3)

您确定str的实际长度与length匹配吗?

http://www.cplusplus.com/reference/clibrary/cstring/strncpy/

  

没有隐含的空字符   附加到目的地的末尾,所以   目的地只会   如果C的长度,则以null结尾   source中的字符串小于num。

答案 2 :(得分:1)

你在哪里看到15个字符?内存管理器可能决定分配超过2个字节(因为优化)。或者在2个字节之后可能还有另一个内存分配,但是某些巧合也属于您的程序。即使您在Visual C ++调试器中看到15个字符并不意味着您可以安全地在代码中访问这些字符,因为您只能保证分配2个字节。

我还在您的代码中看到了其他一些问题:

if (m_p != NULL) m_p = NULL;

如果已经分配了m_p,这将导致内存泄漏。您应该在构造函数中将m_p设置为NULL,然后将以上行替换为:

if (m_p != NULL)  {
  delete[] m_p;
  m_p = NULL;
}

如果你只在构造函数中使用那部分代码,那么简单的m_p = NULL;就可以了。

当你立即重新抛出异常时,try .. catch块也没有多大意义。要么立即在catch块中处理它,要么完全删除try catch。

答案 3 :(得分:1)

您可以使用std::string并观看所有与字符串相关的错误消失吗?

答案 4 :(得分:0)

你如何判断m_p中有“15个符号字符”?

'm_p'(我假设)只是char *。当您使用new分配内存时,它会为您提供指向该内存的指针。分配给你的内存可能只有2个字节长,但在它之后还有更多的内存 - 现在或将很快被分配给其他人。

现在,如果你在调试器中查看*m_p(或打印出来),它将被假定为一个nul-terminate字符串,因此它将保持打印字符,直到它达到0-字节。是否所有这些字符都是分配给您的块的一部分是无关紧要的。

答案 5 :(得分:0)

如果要存储传递的带引号字符串的n个字符,则需要考虑如果源字符串的长度大于或等于length参数,则strncpy不会追加空字符。所以你必须要照顾它:

strncpy(m_p, str, length); // or strncpy(m_p, str, m_size-1);
m_p[length] = '\0'; // or m_p[m_size-1] = '\0'

答案 6 :(得分:0)

我认为您观察的是调试器,显示m_p指向的内存位置。调试器显示char数组字符,直到它看到一个你没有附加到C字符串的空字符,因此你提到的附加了大约15个字符。阅读关于你的问题的其他答案,它们将有助于完全缓解这种影响。

答案 7 :(得分:0)

关于strncpy的其他答案是正确的。这可能是你问的问题的根源。

但是我很担心这句话:

  

我检查m_p是否为null,因为我认为   在调试模式下,MS喜欢设置   地址为0xcccccccc而不是   00000000

它只将未初始化的指针设置为0xcccccccc。这样做有助于捕获代码假定未初始化指针设置为0x00000000的位置。在C ++中,你必须始终记住,如果保持未初始化,原始类型(指针,char,short,int,float等)没有保证值。

因此,如果您在释放模式下未初始化该指针,有时可能是0x00000000,有时它可能是非零的垃圾值。这很可能会导致您尝试做的事情出现问题。

if (m_p != NULL) m_p = NULL;不是解决方案。解决方案是在类的构造函数中将m_p设置为NULL。这样你就可以保证它具有适当的价值。