You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

更改指针类型引发写入访问异常,求内存缓冲区写入问题排查

解决缓冲区写入访问异常:指针算术的常见误区

看来你在测试缓冲区边界写入时踩了指针类型的坑——这种问题我见过不少,核心是没搞清楚指针算术是基于指向类型的大小,而不是字节数。先把你的代码补全(推测你原本想写end = start + ...),再一步步分析:

你的原代码(补全推测部分)

#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* ptr = end - 10; // 假设想写末尾前10个元素
    for (int i = 0; i < 20; i++) {
        *(ptr + i) = 0x1234; // 这里可能触发访问异常
    }
    VirtualFree(start, 0, MEM_RELEASE);
    return 0;
}

问题根源:指针算术的类型依赖

当你对int16_t*类型的指针做加减时,编译器会自动乘以sizeof(int16_t)(也就是2)来计算实际字节偏移。比如:

  • start + size 实际计算的是 (uint8_t*)start + size * sizeof(int16_t)
  • 你申请的内存只有19200字节,但这个偏移会达到19200*2=38400字节,直接超出了申请的内存范围,写入自然会触发访问异常。

正确的缓冲区边界计算方法

有两种可靠的方式来计算缓冲区的末尾指针:

方法1:基于元素个数计算

先算出缓冲区能容纳的int16_t元素总数,再用指针算术:

size_t element_count = size / sizeof(int16_t); // 19200 / 2 = 9600
int16_t* end = start + element_count; // 指向缓冲区末尾的下一个位置(合法的尾后指针)

方法2:用字节指针计算(更直观,适合边界校验)

如果你习惯用字节数来思考,可以先转换成uint8_t*(字节类型指针)计算偏移,再转回来:

uint8_t* start_byte = (uint8_t*)start;
uint8_t* end_byte = start_byte + size;
int16_t* end = (int16_t*)end_byte; // 注意:VirtualAlloc返回的内存是对齐的,所以转换安全

修正后的完整代码

#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);
    
    // 先检查VirtualAlloc是否成功(容易忽略的点!)
    if (start == NULL) {
        return GetLastError();
    }

    // 正确计算缓冲区尾后指针
    size_t element_count = size / sizeof(int16_t);
    int16_t* end = start + element_count;

    // 向末尾前10个位置开始写20个元素(测试边界)
    int16_t* write_ptr = end - 10;
    for (int i = 0; i < 20; i++) {
        // 额外做边界校验,避免溢出(可选但推荐)
        if (write_ptr + i >= end) {
            break; // 或者处理溢出逻辑
        }
        *(write_ptr + i) = 0x1234;
    }

    VirtualFree(start, 0, MEM_RELEASE);
    return 0;
}

额外提醒

  • 永远要检查VirtualAlloc的返回值,如果内存分配失败,start会是NULL,后续操作直接触发异常。
  • 尾后指针(end = start + element_count)是合法的(可以比较,但不能解引用),用来判断指针是否越界非常方便。

内容的提问来源于stack exchange,提问作者Mknsri

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:49:54