Нарушение доступа на va_arg - PullRequest
3 голосов
/ 01 июня 2019

Я пытаюсь создать функцию, которая принимает переменное число матриц в параметрах и умножает тезисы на первый.Я могу прочитать первый, используя 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)

Исключение появляется на первом va_arg из for(...) в теле моего метода.Это код моего метода:

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;

1 Ответ

3 голосов
/ 01 июня 2019

Я не понимаю, что именно вы хотите получить от вашего 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 вызоветn нарушение прав доступа. "

(2) старый C-вариационный синтаксис (на основе va_list, va_arg, va_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<MType> (или другой тип, если хотите).

...