太多的内存被分配给`char * x = new char [32]`

时间:2013-12-18 22:35:48

标签: c++ pointers memory-management visual-studio-2013

#include <iostream>

using namespace std;

struct my_chunk
{
    int size;
    char* data;
};

my_chunk* make_chunk()
{
    my_chunk* new_chunk = new my_chunk;
    new_chunk->size = 32;
    new_chunk->data = new char[32];
    new_chunk->data[0] = 'h';
    new_chunk->data[1] = 'e';
    new_chunk->data[2] = 'l';
    new_chunk->data[3] = 'l';
    new_chunk->data[4] = 'o';
    new_chunk->data[5] = '5';
    new_chunk->data[5] = 'h';
    new_chunk->data[6] = 'e';
    new_chunk->data[7] = 'l';
    new_chunk->data[8] = 'l';
    new_chunk->data[9] = 'o';
    new_chunk->data[10] = 'h';
    new_chunk->data[11] = 'e';
    new_chunk->data[12] = 'l';
    new_chunk->data[13] = 'l';
    new_chunk->data[14] = 'o';
    new_chunk->data[15] = 'h';
    new_chunk->data[16] = 'e';
    new_chunk->data[17] = 'l';
    new_chunk->data[18] = 'l';
    new_chunk->data[19] = 'o';
    new_chunk->data[20] = 'h';
    new_chunk->data[21] = 'e';
    new_chunk->data[22] = 'l';
    new_chunk->data[23] = 'l';
    new_chunk->data[24] = 'o';
    new_chunk->data[25] = 'h';
    new_chunk->data[26] = 'e';
    new_chunk->data[27] = 'l';
    new_chunk->data[28] = 'l';
    new_chunk->data[29] = 'h';
    new_chunk->data[30] = 'e';
    new_chunk->data[31] = 'l';

    return new_chunk;
}

void main()
{
    my_chunk* same_chunk;
    same_chunk = make_chunk();
    std::cout << same_chunk->data;
    std::cout << std::endl;
    system("pause");
}

这是我编译的简单代码。无论我的大小char* data,我都会添加某种形式的填充。它似乎不是一个对齐问题,但也许我错了。

我所知道的是,当我调整char* data = new char[size]时,我可以轻松访问元素[size]以外的内容。我能够访问并设置这些元素的事实告诉我一个大问题已经发生。 为了澄清这意味着在上面的代码中,我可以添加一行new_chunk->data[38] = 'x'而没有任何错误,崩溃或任何东西。我测试了它,它工作正常。

这不是一个大问题,因为我有足够的内存来适应我的数据。唯一的问题是我不明白为什么会这样,并且宁愿修复它。

这也是我的程序的输出:

hellohellohellohellohellohellhel²²²²½½½½½½½½¯■¯■
Press any key to continue . . .

编辑:

这已经引发了有用的见解,或许我可以获得与这一切相关的一点帮助。 为什么Visual Studio 2013会显示超出其长度的char *?它显示了“hellohellohellohellohellohellhel²²²²½½½½½½½■■”这对我来说是在分配太多的内存。作为旁注,输出始终相同(到目前为止)。这是我调试时,查看变量,它显示输出的确切内容。

4 个答案:

答案 0 :(得分:3)

char*需要'\0'正确打印std::cout。所以这一行std::cout << same_chunk->data;将在内存中迭代,直到找到零...

这会导致崩溃,打印垃圾......

顺便说一下,在C ++中没有对指针访问进行绑定检查,所以无论何时编写data[X],程序都会尝试对data + X时间进行大约data的大小调整。元素(这里是char)。

如果你想要绑定访问(并且你想要它),可以使用std::string(字符整齐)或std::vector(任何东西都很整洁)。

答案 1 :(得分:2)

C ++并没有真正检查以确保数组索引位于为该数组分配的初始内存块中。当您访问“额外”内存时,您基本上只是访问一些不相关的内存并将其作为一个字符进行转换。它不是作为数组的一部分进行分配,只是可访问就像它一样。将值分配给那些随机存储器位置只是随机覆盖内存......不好的想法。

答案 2 :(得分:2)

以下是基于较低级别视图的另一个视角:

当您调用new(或malloc)时,库(libc?)将从OS请求一些内存。此内存最有可能是页面形式(即4K,2M等大字节)。根据库用于管理动态内存的算法,可能会发生以下几种情况:

  1. 您的数据[]指针恰好位于此页面的后边缘,并且您收到页面错误(程序崩溃,预期的行为)

  2. 更有可能的是,图书馆在页面中间为您分配了一些空间。由于C ++不进行边界检查(由其他人回答),因此它将此数据*指针视为指向内存中字节列表的指针。由于分配给堆的空间的粒度相当大,因此您可以访问具有垃圾值的映射页(即没有程序崩溃)(即未初始化的值)。

  3. 另外需要注意的是,当你请求一个32字节长的内存块时,没有任何内容可以指示你得到一个完全 32字节长的内存块。 new []可能会给你一个1024字节长或400000字节长的区域。唯一的保证是至少 32字节长。因此,这是您的程序不会崩溃的另一个原因(尽管不是主要原因)。

答案 3 :(得分:1)

C和C ++不进行边界检查。所以基本上你很幸运,当你访问超出你分配的内存范围的位置时,你没有得到段错误。

[38]符号基本上表示移动到数据的等效地址+ 38 * sizeof(char *)。因此,如果这个空间被标记为毒药,那你就不幸了。