Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Acces violation on va_arg

I am trying to create a function that takes a variable number of matrix in parameters and multiply theses to a first one. I can read a first one using va_arg, but the next call of va_arg will cause an access violation.

Here is how i declare my method :

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

And here is how i call it :

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

The exception appears on the first va_arg of the for(...) in the body of my method. This is the code of my method:

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;
like image 800
colin Avatar asked Jan 27 '26 02:01

colin


1 Answers

I don't understand what you exactly want obtain from your OCPChangementDeBase() method, anyway... maybe I'm wrong... but it seems to me that there are a couple of important points, regarding variadic functions, that you don't know.

(1) the old C variad syntax

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

doesn't mean that b is a variadic list of integer.

That declaration is equivalent (the last comma is optional) to

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

so, with both declarations, you have a b integer (a single b integer) and an unnamed list of variadic arguments.

So given you method

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

and calling it

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

you have that

  • MATVecteur become mat1
  • uiNbMatricesPassages become 2
  • MAPMatrices become matP1
  • the unnamed variadic list ... become matP2

So, if you're expecting two arguments in the unnamed varidic list, you have only one and I'm not surprised that "the next call of va_arg will cause an access violation."

(2) the old C variadic syntax (va_list, va_arg, va_start based) remains available in C++ but, as far I know, works only for PODs (Plain Old Data) types.

So, as far I know, your code is UB (undefined bahaviour) because matP2 (I suppose) isn't POD.

Fortunately C++ (starting from C++11) introduce variadic templates that are compatible also with not PODs types.

So, I suppose, you count write your method as follows or something similar

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;
 }

You can also add some constraints (look for SFINAE) to impose that MTs... types are exactly (or, maybe better, convertible to) CMatricePassage<MType> (or another type, if you want).

like image 158
max66 Avatar answered Jan 28 '26 15:01

max66



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!