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

标签 c pointers memory allocation

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

给定这段代码,它只是分配内存并尝试在它的最后写入:

#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,无论使用什么类型?

最佳答案

VirtualAlloc 中的第二个参数是以字节 为单位分配的大小。如果你想要一个包含 19200 个 16 位整数的数组,你应该调用它

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

那么下一行就ok了:

int16_t *end = start + size;

在这里你有效地得到了

int16_t *end = &start[size];

开始前 19200*2 个字节。

指针算法使用要跳过的元素数,而不是字节数。向 int32_t* 加 1 会跳过 4 个字节,向 int16_t* 加 1 会跳过 2 个字节。

我不知道为什么 int 大小写对你有用,因为它不应该。

关于更改指针类型导致写访问异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49496748/

相关文章:

c - 使用指针作为参数传递

c - 为什么这个指针操作会失败?

C++ 地址和指针

c++ - 为什么或为什么不在 C++ 中使用 memset?

python - 从内存中删除类实例

PHP "Uninclude"或从内存中删除?

c - 如何获取 NULL 作为返回值?

计算文本文件 C 中的帐户数量

c++ - C/C++ 字符串文字中的未知元字符?

pointers - 如何在golang中正确打印出指针变量