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_list
、va_arg
、va_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>
(或其他类型,如果您愿意) .
我正在尝试创建一个函数,该函数在参数中采用可变数量的矩阵并将这些矩阵乘以第一个矩阵。
我可以使用 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_list
、va_arg
、va_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>
(或其他类型,如果您愿意) .