【问题标题】:Acces violation on va_argva_arg 上的访问冲突
【发布时间】:2019-06-01 10:45:06
【问题描述】:

我正在尝试创建一个函数,该函数在参数中采用可变数量的矩阵并将这些矩阵乘以第一个。 我可以使用va_arg 读取第一个,但下一次调用va_arg 会导致访问冲突。

这是我声明我的方法的方式:

template<class MType>
static CMatrice<MType> COperationsComplexesMatricesPassages::OCPChangementDeBase
   (CMatrice<MType> & MATVecteur, unsigned int uiNbMatricesPassages,
    CMatricePassage<MType> MAPMatrices...)

我是这样称呼它的:

COperationsComplexesMatricesPassages::OCPChangementDeBase(mat1, 2, matP1, matP2)

异常出现在我的方法主体中for(...) 的第一个va_arg 上。 这是我的方法的代码:

unsigned int uiIndice;
unsigned int uiBaseArriveePrecedente;

va_list args;
va_start(args, MAPMatrices);

CMatrice<MType> MATResult(MATVecteur);
CMatricePassage<MType> MAPMatricePass = va_arg(args, CMatricePassage<MType>);

MATResult = MATResult * MAPMatricePass;

uiBaseArriveePrecedente = MAPMatricePass.MAPGetBaseArrivee();
for (uiIndice = 1; uiIndice < uiNbMatricesPassages; uiIndice++) {
    CMatricePassage<MType> MAPMatricePass2 = va_arg(args, CMatricePassage<MType>);
    if (uiBaseArriveePrecedente != MAPMatricePass2.MAPGetBaseDepart()) {
        CException EXCError(EXC_ChangementImpossible);
        throw EXCError;
    }
    uiBaseArriveePrecedente = MAPMatricePass2.MAPGetBaseArrivee();
    MATResult = MATResult * MAPMatricePass2;
}

return MATResult;

【问题讨论】:

    标签: c++ templates variadic-functions variadic


    【解决方案1】:

    无论如何,我不明白你到底想从你的OCPChangementDeBase() 方法中获得什么......也许我错了......但在我看来,关于可变参数函数,有几点很重要,你不知道的。

    (1) 旧的 C 变量语法

    void foo (int a, int b...)
    

    并不意味着b 是一个可变整数列表。

    该声明等效于(最后一个逗号是可选的)

    void foo (int a, int b, ...)
    

    因此,对于这两个声明,您都有一个 b 整数(单个 b 整数)和一个未命名的可变参数列表。

    给你方法

    template<class MType>
    static CMatrice<MType>
    COperationsComplexesMatricesPassages::OCPChangementDeBase
       (CMatrice<MType> & MATVecteur, unsigned int uiNbMatricesPassages,
        CMatricePassage<MType> MAPMatrices...)
    

    并调用它

    COperationsComplexesMatricesPassages::OCPChangementDeBase(mat1, 2, matP1, matP2)
    

    你有这个

    • MATVecteur变成mat1
    • uiNbMatricesPassages变成2
    • MAPMatrices变成matP1
    • 未命名的可变参数列表...变成matP2

    因此,如果您在未命名的可变参数列表中期望 两个 参数,那么您只有一个,我并不感到惊讶“下一次调用 va_arg 将导致访问冲突。”

    (2) 旧的 C 可变参数语法(基于va_listva_argva_start)在 C++ 中仍然可用,但据我所知,它仅适用于 POD(普通旧数据)类型。

    所以,据我所知,您的代码是 UB(未定义的行为),因为 matP2(我想)不是 POD。

    幸运的是,C++(从 C++11 开始)引入了与非 POD 类型兼容的可变参数模板。

    所以,我想,你算写你的方法如下或类似的东西

    template <typename MType, typename ... MTs>
    static auto COperationsComplexesMatricesPassages::OCPChangementDeBase
       (CMatrice<MType> & MATVecteur, MTs ... MAPMatrices)
     {
       auto MatResult { MatVectour };
    
       ( MatResult *= MapMatrices, ... ); // template folding; only from C++17
    
       return MatResult;
     }
    

    您还可以添加一些约束(查找 SFINAE)以强制使 MTs... 类型完全(或者,可能更好,可转换为)CMatricePassage&lt;MType&gt;(或其他类型,如果您愿意)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-06
      • 2013-02-26
      相关资源
      最近更新 更多