我试图弄清楚在缓冲区末尾附近写入一 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/