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

跨平台(Windows/Linux/Android)系统API错误处理技术咨询

跨平台程序错误处理问题

程序背景

我正在开发一款跨平台程序,支持以下平台:

  • Windows x64
  • Linux x64
  • Windows ARM
  • Linux ARM
  • Android ARM

该程序需对接最多20个串口,通过MQTT或ReST-JSON与服务器连接,应用中大量使用异步操作与线程。

技术问题

  1. 能否使用libc的errno整型变量处理WIN API错误?还是必须在Windows平台使用GetLastError,在Linux和Android平台使用errno?
  2. GetLastError()是否线程安全?
  3. strerror_s是否线程安全?
  4. 若编译时选择C11或更高版本,strerror_s是否可在Linux和Android平台使用?

当前实现代码

//返回最后一次错误的字符串形式,无错误则返回空字符串。
std::string GetLastErrorAsString(void)
{
#ifdef _WIN64
    //获取错误消息ID(若存在)。
    DWORD errorMessageID = ::GetLastError();
    if (errorMessageID == 0) 
    {
        return std::string(); //未记录错误消息
    }

    LPSTR message_buffer = nullptr;

    //请求Win64返回该消息ID对应的字符串版本。
    //传入的参数指示Win64为我们创建存储消息的缓冲区(因为我们尚不清楚消息字符串的长度)。
    size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&message_buffer, 0, NULL);

    //将错误消息复制到std::string中。
    std::string error_message(message_buffer, size);

    //释放Win64分配的字符串缓冲区。
    LocalFree(message_buffer);

    return error_message;
#elif __linux__ || __ANDROID__
    if (errno == 0)
    {
        return std::string(); //未记录错误消息
    }
    size_t error_message_length = strerrorlen_s(errno) + 1;
    std::array<char, error_message_length> error_message;
    //char errmsg[errmsglen];
    strerror_s(error_message.data(), error_message_length, errno);
    return std::string(error_message.data());
#endif
}

问题解答

1. WIN API错误与errno的使用限制

不能用errno处理WIN API错误。WIN API调用失败时,只会通过GetLastError()返回错误码,不会主动设置errno;只有调用C标准库函数(如fopen、read)时,Windows才会同步更新errno。因此必须在Windows平台用GetLastError()获取WIN API的错误,Linux和Android平台用errno获取系统调用或标准库的错误。

2. GetLastError()的线程安全性

GetLastError()是线程安全的。每个线程都有独立的错误码存储区域,调用该函数只会返回当前线程的最后错误,不会与其他线程的错误码混淆。但要注意,必须在WIN API调用失败后立即调用GetLastError(),后续的API调用可能会覆盖当前线程的错误码。

3. strerror_s的线程安全性

strerror_s是线程安全的。作为C11引入的安全函数,它要求调用者提供私有缓冲区,避免了strerror使用共享静态缓冲区导致的线程竞争问题,只要传入的缓冲区是当前线程独有的,就不会有线程安全风险。

4. Linux和Android平台对C11标准strerror_s的支持

编译时指定C11或更高版本后,主流Linux发行版(如Ubuntu、CentOS)的GCC/Clang编译器均支持strerror_s;Android NDK从r15版本开始也支持C11标准的strerror_s,部分老版本NDK需要显式启用C11支持(比如在CMake中设置CMAKE_C_STANDARD 11)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 22:40:38