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

C++中memmove_s函数异常处理相关报错的解决方案咨询

问题根因说明

  • memmove_s属于C标准安全函数,参数校验失败时默认触发的是结构化异常(SEH),不是C++标准异常,所以普通try/catch无法捕获。
  • 报错Cannot use __try in functions that require object unwinding是因为微软SEH的__try/__except块默认不支持和包含RAII对象(你的函数里有std::string类型参数,退出时需要调用析构函数做对象自动清理)的函数混用,编译器不允许该写法。
  • 你代码中memmove_s传参destSize + 1是错误逻辑,destSize本身就应该是目标缓冲区的总可用大小,加1会导致越界校验失效,反而会引入安全风险。

可行解决方案

方案1:禁用安全函数异常触发,判断返回值处理(最推荐)

memmove_s本身会通过返回值标识错误状态,不需要依赖异常处理,你只需要关闭CRT默认的异常触发逻辑即可:

  1. 全局自定义无效参数处理函数,避免CRT自动抛异常:
#include <stdlib.h>
#include <crtdbg.h>

// 全局设置仅需调用一次
void my_invalid_param_handler(const wchar_t* expression, const wchar_t* function, const wchar_t* file, unsigned int line, uintptr_t reserved)
{
    // 可按需加错误日志,不需要抛异常
}

// 程序初始化阶段执行一次
_set_invalid_parameter_handler(my_invalid_param_handler);
_CrtSetReportMode(_CRT_ASSERT, 0); // 关闭CRT断言弹窗
  1. 直接判断memmove_s返回值处理错误,不需要任何异常捕获逻辑:
extern "C" void get_str_value(string src, char* dest, unsigned int destSize)
{
    errno_t r = memmove_s((void*)dest, destSize, src.c_str(), src.size() + 1);
    if (r == 0) {
        cout << "拷贝成功,r=" << r << endl;
    } else if (r == ERANGE) {
        cout << "目标缓冲区大小不足,拷贝失败" << endl;
        // 按需加错误处理逻辑
    } else {
        cout << "其他错误,错误码:" << r << endl;
    }
}

方案2:抽离SEH逻辑到无RAII对象的独立函数

如果必须用__try/__except捕获异常,把拷贝逻辑抽离到没有需要自动析构的C++对象的纯C风格函数中即可:

// 内层纯C风格函数,无RAII对象,支持__try/__except
extern "C" int safe_memmove(void* dest, size_t destSize, const void* src, size_t srcSize)
{
    __try
    {
        return memmove_s(dest, destSize, src, srcSize);
    }
    __except (filter(GetExceptionCode(), GetExceptionInformation()))
    {
        std::cout << "捕获到SEH异常" << std::endl;
        return -1;
    }
}

// 外层函数处理RAII对象,不需要加__try
extern "C" void get_str_value(string src, char* dest, unsigned int destSize)
{
    int r = safe_memmove(dest, destSize, src.c_str(), src.size() + 1);
    cout << "r=" << r << endl;
}

方案3:开启/EHa编译选项(不推荐)

在Visual Studio项目属性中,找到C/C++ -> 代码生成 -> 启用C++异常,选择是,但有 SEH 异常 (/EHa),开启后普通C++ try/catch(...)就可以捕获SEH异常,不需要改业务代码。但该选项会修改C++异常的默认处理逻辑,可能会把内存访问越界等致命异常也捕获,引入隐性风险,非必要不建议使用。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 03:57:01