首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> 關於VC++

使用 _matherr 捕獲數學函數運行時異常

     編輯:關於VC++

問題背景

調用 asin、log、pow 等數學函數時,若參數超出定義域會產生運行時錯誤。手工檢查參數(特別是 pow(x,y) 的複雜定義域)繁瑣且易出錯。

VC++ 提供的解決方案:_matherr

原型:int _matherr(struct _exception *except);

編譯器會在數學庫函數檢測到錯誤時自動調用該函數,無需顯式調用。

_exception 結構成員

成員含義
int type異常類型
char *name出錯函數名
double arg1, arg2函數參數
double retval函數返回值(可修改)

異常類型常量

  • _DOMAIN:定義域錯誤
  • _SING:奇異點錯誤
  • _OVERFLOW:溢出
  • _PLOSS:精度部分遺失
  • _TLOSS:精度完全遺失
  • _UNDERFLOW:下溢

返回值約定

  • 返回 0:顯示默認錯誤信息,設置 errno
  • 返回非 0:抑制錯誤信息,errno 不變,可通過修改 retval 返回自定義值

示例:自定義 pow 錯誤處理

#include <math.h> #include <stdio.h>
int _matherr(struct _exception *except) {
    static char* errStr[] = {"_DOMAIN","_SING","_OVERFLOW","_PLOSS","_TLOSS","_UNDERFLOW"};
    printf("Error function: %s\n", except->name);
    printf("Args: %g, %g\n", except->arg1, except->arg2);
    printf("Type: %s\n", errStr[except->type]);
    printf("Default retval: %g\n", except->retval);
    except->retval = 1234;  // 自定義返回值
    printf("New retval: %g\n", except->retval);
    return 1; // 抑制默認錯誤輸出
}

void main() {
    double x = -1.23, y = -1.1, z;
    z = pow(x, y); // 觸發 _SING
    printf("%g\n", z); // 輸出 1234
}

輸出:

Error function: pow
Args: -1.23, -1.1
Type: _SING
Default retval: -1.#IND
New retval: 1234
1234

MSDN 官方示例:修正 log 定義域錯誤

int _matherr(struct _exception *except) {
    if (except->type == _DOMAIN) {
        if (strcmp(except->name, "log") == 0) {
            except->retval = log(-except->arg1);
            printf("Special: using absolute value: %s: _DOMAIN error\n", except->name);
            return 1;
        }
        if (strcmp(except->name, "log10") == 0) {
            except->retval = log10(-except->arg1);
            printf("Special: using absolute value: %s: _DOMAIN error\n", except->name);
            return 1;
        }
    }
    printf("Normal: ");
    return 0; // 其他錯誤走默認處理
}

總結

_matherr 提供集中式數學錯誤處理機制,適用於參數來源不可控(用戶輸入、中間計算結果)的場景,避免大量分散的 if 判斷。注意:僅對 Microsoft C 運行時庫的數學函數有效。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved