2017-02-05 13 views
0

В нижеприведенном фрагменте кода вставьте Instruction в BasicBlock, на который указывает Function::iterator bs. Внутренняя петля выполняет итерации над инструкциями, содержащимися в этом BasicBlock.Как сохранить итерирование структуры данных после вставки в нее элементов?

Теперь, после того, как внутренний цикл вставляет эти инструкции, программа переходит в бесконечный цикл с последовательностью команд:

and 
mul 
xor 
and 
mul 
xor 
and 
mul 
xor 
and 
mul 
xor 
and 
mul 
xor 
and 
mul 
... 

Как бы вставить в структуру данных итерируемый более, избегая при этом идти в бесконечном цикл?

Как-то итератор гаснет (или он признан недействительным). Есть ли распространенная идиома для решения этой проблемы?

for (Function::iterator bs = F.begin(), be = F.end(); bs != be; ++bs) { 
    for (BasicBlock::iterator is = bs->begin(), ie = be->end(); is != ie; ++is) { 
     Instruction& inst = *is; 
     BinaryOperator* binop = dyn_cast<BinaryOperator>(&inst); 

     if (!binop) { 
      continue; 
     } 

     unsigned opcode = binop->getOpcode(); 
     errs() << binop->getOpcodeName() << "\n"; 

     if (opcode != Instruction::Add) { 
      continue; 
     } 

     IRBuilder<> builder(binop); 
     Value* v = builder.CreateAdd(builder.CreateXor(binop->getOperand(0), binop->getOperand(1)), 
            builder.CreateMul(ConstantInt::get(binop->getType(), 2), 
                 builder.CreateAnd(binop->getOperand(0), binop->getOperand(1)))); 

     ReplaceInstWithValue(bs->getInstList(), is, v); // THINGS GO WRONG HERE! 
    } 
} 
+0

Я просто создаю новый список и добавляю к нему вместо того, чтобы изменять коллекцию, которую вы повторяете. Комбинация карт/фильтров также должна работать. – Carcigenicate

+0

Как выглядит 'ReplaceInstWithValue'? – 1201ProgramAlarm

+0

http://llvm.org/docs/doxygen/html/BasicBlockUtils_8cpp_source.html#l00189 – Shuzheng

ответ

0

К сожалению, вы не в состоянии обеспечить достаточное количество деталей, но я сильно подозреваю, что вы вставляя новый элемент в контейнер таким образом, что существующие итераторы (для других элементов) являются недействительными. Это обычное поведение для многих классов контейнеров, например. std::vector<>::insert(), что делает недействительными все существующие итераторы, если новый size() превышает capacity() (в противном случае действительны только существующие итераторы до элементов вставки).

Способ избежать использования контейнера, который не страдает от этой проблемы, например. a std::list<>, поскольку std::list<>::insert() не аннулирует существующий итератор или ссылку.

+0

Итак, как бы вы справились с этой проблемой? – Shuzheng