va_arg 上的访问冲突

Acces violation on va_arg

我正在尝试创建一个函数,该函数在参数中采用可变数量的矩阵并将这些矩阵乘以第一个矩阵。 我可以使用 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;

我不明白你到底想从你的 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

因此,如果您期望在未命名的可变参数列表中有 两个 个参数,那么您只有一个参数,"the next call of va_arg will cause an access violation."

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

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

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

所以,我想,您可以按如下或类似的方式编写您的方法

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<MType>(或其他类型,如果您愿意) .