动态内存分配问题

时间:2010-02-19 22:57:11

标签: c++ visual-c++ dynamic-memory-allocation

使用指针在堆上分配动态内存时

char *buffer_heap = new char[15];

它将在内存中表示为:

 ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍýýýý««««««««þþþ

为什么最后没有一个NULL终止字符而不是“««««««««?

7 个答案:

答案 0 :(得分:22)

Í是字节0xCD,Windows调试分配器写入您的15字节内存,表明它是未初始化的堆内存。未初始化的堆栈将为0xCC。这个想法是,如果你曾经读过记忆并意外地得到这个价值,你可以自己想一想,“嗯,我可能忘记了这个”。此外,如果您将其作为指针读取并取消引用它,那么Windows将使您的进程崩溃,而如果未初始化的缓冲区填充了随机或任意值,那么有时您会得到一个有效的指针,并且您的代码可能会导致所有各种麻烦。 C ++没有说明未初始化内存的值是什么,非调试分配器不会浪费时间为每个分配填充特殊值的内存,所以你绝不能依赖那个值。

接下来是4个字节的ý(字节0xFD),Windows调试分配器使用它来指示缓冲区末尾的越界区域。我的想法是,如果你发现自己在调试器中写了一个看起来像这样的区域,你可以想“嗯,我可能在这里超出了我的缓冲区”。此外,如果释放缓冲区时值已更改,则内存分配器可以警告您代码错误。

«是字节0xAB,þ是0xFE。据推测,这些也可用作引人注目的(它们不是合理的指针或偏移量,因此它们不构成堆结构的一部分)。我不知道它们的含义,可能还有更多的保护数据,如0xFD。

最后,我猜,你已经找到了一个0字节,超出15字节缓冲区末尾的第16个字节(即从它开始算起的第31个字节)。

在不提及您使用Windows的情况下将问题称为“C ++”表明这就是C ++的行为方式。它不是,它是一个C ++实现的行为,特定的编译器选项和/或链接的dll。 C ++不允许你读取缓冲区的末尾,微软对你很好,让你逃脱它不会崩溃或更糟。

答案 1 :(得分:6)

您尚未初始化该内存。你只是看到那里已有的东西......

答案 2 :(得分:4)

您需要初始化它。通过显式调用默认构造函数,可以将内置类型初始化为零:

char *b = new char[15]();

答案 3 :(得分:1)

虽然每个C样式字符串都表示为字符序列,但并不是每个字符序列都是字符串。

当您直接指定字符串文字或自己添加字符串文字时,\ 0通常会出现。并且只有将该数组视为具有将\ 0考虑在内的函数的字符串才有意义。

如果您只是分配内存并且没有初始化它,那么它就是随机的东西。那里可能有0或者可能没有 - 你将不得不在后续步骤中放置有意义的东西。是否要将某些东西变成字符串取决于你。

答案 4 :(得分:1)

因为char是本机类型,所以它未初始化。这就是C ++的原因(它是C的遗产)。

接受它并且0自己终止它:

char *buffer_heap = new char[15];
*buffer_heap = '\0';

或者如果您想要初始化整个缓冲区:

std::fill(buffer, buffer + 15, 0);

答案 5 :(得分:1)

只有在分配了已初始化的类型时才会初始化它。否则,如果你想要一些有意义的值,你必须自己写。

另一方面,更好的答案是你不应该首先这样做。忘记new[]存在,不要回头。

答案 6 :(得分:0)

在Linux上的GNU C ++(g ++)中,这个程序退出很快:

#include <algorithm>
#include <iterator>
#include <vector>
#include <cstddef>
#include <cstdlib>
#include <iostream>

namespace {

class rand_functor {
 public:
   int operator ()() const { return ::std::rand(); }
};

}

int main()
{
   using ::std::cout;
   using ::std::vector;
   using ::std::ostream_iterator;
   using ::std::generate;
   using ::std::equal;
   using ::std::copy;

   char *tmp = new char[1000];
   // This just fills a bunch of memory with random stuff, then deallocates it
   // in the hopes of making a match more likely.
   generate(tmp, tmp+1000, rand_functor());
   delete[] tmp;
   vector<char *> smalls;
   smalls.push_back(new char[15]);
   do {
      smalls.push_back(new char[15]);
   } while (equal(smalls[0], smalls[0]+15, smalls[smalls.size() - 1]));
   cout << "        In one allocation I got: [";
   copy(smalls[0], smalls[0]+15, ostream_iterator<char>(cout));
   cout << "]\nAnd in another allocation I got: [";
   copy(smalls[smalls.size() - 1], smalls[smalls.size() - 1]+15,
        ostream_iterator<char>(cout));
   cout << "]\n";
   cout << "It took " << smalls.size() << " allocations to find a non-matching one.\n";
   return 0;
}