在c++的指针数组中,内存过度提交会导致指针被存储在不连续的内存块中

In an array of pointers in C++ does memory overcommitting result in the pointers to be stored in non-contiguous blocks of memory?

本文关键字:内存 指针 不连续 存储 数组 c++ 提交      更新时间:2023-10-16

我在XCode中编写一些代码,当我部分填充数组时注意到一些有趣的事情。我的代码基本上是这样的(这只是一个简单的例子):

#include <iostream>
using namespace std;
int main(){
    int** array = new int*[20];
    for(int k = 0; k < 20; k+=3){
        array[k] = &k;
    }
    for(int k = 0; k < 20; k++){
        bool ptrVal = (array[k] == nullptr);
        cout << k << ": " << ptrVal << endl;
    }
}

这段代码最终输出如下:

0: 0
1: 0
2: 0
3: 0
4: 0
5: 0
6: 0
7: 1
8: 1
9: 0
10: 1
11: 1
12: 0
13: 1
14: 1
15: 0
16: 1
17: 1
18: 0
19: 1

0: 0
1: 1
2: 1
3: 0
4: 1
5: 1
6: 0
7: 1
8: 1
9: 0
10: 1
11: 1
12: 0
13: 1
14: 1
15: 0
16: 1
17: 1
18: 0
19: 1

之后我读了下面一篇关于操作系统如何过度使用内存的文章:指针数组

的c++内存分配

操作系统是否故意为已部分填充的指针数组分配不连续的内存块?如果是这样,它为什么会这样做?我的示例代码中显示的结果可能是什么原因?

你有:

int** array = new int*[20];
for(int k = 0; k < 20; k+=3){
    array[k] = &k;
}

之后,k[1], k[2], [k4], k[5] ..不初始化。它们不是由分配指针的那一行设置为nullptr的。

因此,

    bool ptrVal = (array[k] == nullptr);

是未定义行为的原因。

你可以使用以下命令使指针在分配时等于nullptr:

int** array = new int*[20]{};

假设数组中未初始化的元素被设置为0。事实并非如此。如果加上

    memset(array, 0, sizeof(*array)*20);

在第一个循环之前,那么你的输出将是你所期望的。