更改指针类型会导致写访问异常

时间:2018-03-26 16:55:41

标签: c pointers memory allocation

我试图弄清楚在缓冲区末端附近写一块内存是否会溢出,但是我遇到了一个奇怪的问题,我想这是由于对类型的错误有些误解指针工作。

鉴于此代码,它只分配内存并尝试在其末尾写入:

#include <Windows.h>
#include <stdint.h>

int main() {
    size_t size = 19200;
    int16_t* start = (int16_t*) VirtualAlloc(0, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
    int16_t* end = start + size;
    int16_t* writeToEnd = end - sizeof(int16_t);
    *writeToEnd = 1;

    return 0;
}

我在writeToEnd收到了非法的写入异常。但是,如果我将所有内容更改为int

#include <Windows.h>
#include <stdint.h>

int main() {
    size_t size = 19200;
    int* start = (int*) VirtualAlloc(0, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
    int* end = start + size;
    int* writeToEnd = end - sizeof(int);
    *writeToEnd = 1;

    return 0;
}

一切正常。我会理解,如果某些值会导致int16_t - 类型溢出,但通过手动检查所有值,一切似乎都可以。 Visual Studio内存窗口显示可用内存小于end计算到的内容。

我误解了什么?无论使用何种类型,都不应该pointer + size == endOfBuffer吗?

1 个答案:

答案 0 :(得分:1)

VirtualAlloc中的第二个参数是要在 bytes 中分配的大小。如果你想要一个19200 16位整数的数组,你应该调用它

int16_t* start = (int16_t*) VirtualAlloc(0, size*sizeof(int16_t), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);

然后下一行就可以了:

int16_t *end = start + size;

在这里你实际上是

int16_t *end = &start[size];

在开始之前是19200 * 2字节。

指针算术使用要跳过的元素数,而不是字节数。将1添加到int32_t *跳过4个字节,将1添加到int16_t *跳过2个字节。

我不知道为什么int case适合你,因为它不应该。