C ++ векторная проблема - PullRequest
       3

C ++ векторная проблема

1 голос
/ 28 февраля 2011

У меня странное поведение с вектором в C ++. Я надеялся, что кто-нибудь мне поможет.У меня есть такой вектор:

vector<Instruction*> allInstrs; 

структура для инструкции выглядит следующим образом:

struct Instruction : simple_instr
{
    InstrType type;
    Instruction(const simple_instr& simple) : simple_instr(simple) 
    {
        type = Simple;
        loopHeader = false;
        loopTail = false;
    }
    int Id;
    bool loopHeader;
    bool loopTail;
};

проблема у меня заключается в следующем:

мне нужновыполнять итерацию по каждой инструкции, извлекать определенные поля и использовать их для анализа команд в векторе.Чтобы сделать это, я в основном делал

VariableList Variables;

void GenerateVariableList()
    {
        for (int i = 0; i < allInstrs.size(); i++)
        {           
             Variables.Add(allInstrs[i]);
        }
        Variables.RemoveDuplicates();
    }

Список переменных определяется как

struct VariableList
{
    void Add(simple_instr* instr)
    {
        PrintOpcode(instr);
        switch(instr->opcode)
            {
                case STR_OP:
                case MCPY_OP:
                    Add(instr->u.base.src1);
                    Add(instr->u.base.src2);
                    break;              
                case LDC_OP: 
                    Add(instr->u.ldc.dst);
                    break;              
                case BTRUE_OP:
                case BFALSE_OP: 
                    Add(instr->u.bj.src);
                    break;              

                case CALL_OP:
                    cout << "CALL OP" <<endl;
                    break;

                case MBR_OP:                    
                    Add(instr->u.mbr.src);
                    break;          

                case RET_OP:
                    if (instr->u.base.src1 != NO_REGISTER)
                        Add(instr->u.base.src1);
                    break;              

                case CVT_OP:
                case CPY_OP:
                case NEG_OP:
                case NOT_OP: 
                case LOAD_OP: 
                    Add(instr->u.base.dst);
                    Add(instr->u.base.src1);
                    break;

                case LABEL_OP:
                case JMP_OP:
                    break;                      

                default:
                    Add(instr->u.base.dst);
                    Add(instr->u.base.src1);
                    Add(instr->u.base.src2);
                    break;

            }
    }

    void Add(Variable var)
    {
        variableList.push_back(var);
    }

    void RemoveDuplicates()
    {
        if (variableList.size() > 0)
        {
            variableList.erase(unique(variableList.begin(), variableList.end()), variableList.end());
            currentID = variableList.size();
        }
    }

    VariableList()
    {
        currentID = 0;
    }

    VariableList(VariableList& varList, bool setLiveness = false, bool LiveVal = false)
    {
        currentID = 0;
        for (int i = 0; i < varList.size(); i++)
        {
            Variable var(varList[i]);
            if (setLiveness)
            {
                var.isLive = LiveVal;
            }
            variableList.push_back(var);
        }
    }

    Variable& operator[] (int i)
    {
        return variableList[i];
    }

    int size()
    {
        return variableList.size();
    }

    vector<Variable>::iterator begin()
    {
        return variableList.begin();
    }

    vector<Variable>::iterator end()
    {
        return variableList.end();
    }

    protected:
        int currentID;
        vector<Variable> variableList;

        void Add(simple_reg* reg, bool checkForDuplicates = false)
        {   cout << "Register Check" <<endl;
            if (reg == null)
            {
                cout << "null detected" << endl;
                return;
            }
            if (reg->kind == PSEUDO_REG)
            {   

                if (!checkForDuplicates || (checkForDuplicates && find(variableList.begin(), variableList.end(), reg->num) != variableList.end()))
                {
                    cout << "Adding... Reg  " << reg->num << endl;
                    Variable var(reg->num, currentID);

                    variableList.push_back(var);
                    currentID++;
                }
            }
        }

};

Когда я делаю это, каждая инструкция переходит к оператору по умолчанию, даже если я знаюна самом деле некоторые инструкции не должны.Если я изменю GenerateVariableList на

void GenerateVariableList()
    {
        for (int i = 0; i < allInstrs.size(); i++)
        {   
            PrintOpcode(allInstrs[i]);
            Variables.Add(allInstrs[i]);
        }
        Variables.RemoveDuplicates();
    }

, так что теперь есть второй PrintOpCode в дополнение к тому, что в Variables.Add, программа будет работать правильно.Я не могу понять, почему добавление второго PrintOpcode заставляет его работать правильно.Весь код операции печати - это функция с оператором switch, которая просто печатает конкретную строку в зависимости от значения одного из полей simple_instr.

Переменные VariableList содержатся внутри отдельной структуры CFG

Если вам нужна дополнительная информация / код, я могу ее предоставить.Если ответ очевиден, я прошу прощения, я не очень часто программирую на C ++

РЕДАКТИРОВАТЬ:

Один из оставшихся ответов, удаленный сейчас, принес мне исправление.

Раньше я делал

static vector<Instruction*> ConvertLinkedListToVector(simple_instr* instructionList)
    {
        vector<Instruction*> convertedInstructions;
        int count = 0;
        for (simple_instr* current = instructionList; current; count++, current = current->next)
        {
            //Instruction* inst = new Instruction(*current);
            Instruction inst = Instruction(*current);
            inst.Id = count;
            convertedInstructions.push_back(&inst);
        }
        return convertedInstructions;
    }

, чтобы сделать вектор, но после прочтения этого ответа я снова изменил его на использование "new", и теперь он работает правильно.Спасибо за помощь, извините за тупой вопрос хех

Ответы [ 4 ]

1 голос
/ 28 февраля 2011

Возможно, это не связано с вашей проблемой, но, безусловно, является потенциальным источником странного поведения: ваш конструктор Instruction(const simple_instr& simple) может быть вызван, когда вы этого не намерены.Отметьте это как явное ...

explicit Instruction(const simple_instr& simple) ...

Если это вызывает ошибки компилятора, то это прогресс :-) Возможно, вам придется написать конструктор копирования, чтобы они исчезли, и явно вызвать старый конструктор там, где вам нужнок.

1 голос
/ 28 февраля 2011

Итак, есть несколько подозрительных наблюдений:

  • В вашем определении VariableList вы используете тип с именем Variable - как этот тип определен?
  • Итерации по контейнеру должны выполняться с использованием итератора:

for (vector<Intruction *>::iterator it = allInstrs.begin(); 
     it != allInstrs.end();
     ++it) {
    Variables.Add(*it);
}

  • Вам следует рассмотреть использование вектора boost::shared_ptr или boost::ptr_vector вместо вектора указателей.
1 голос
/ 28 февраля 2011

Скорее всего, const simple_instr& simple, переданный вашему конструктору, выходит из области видимости, и вы сохраняете недопустимую ссылку / указатель на simple_instr.

0 голосов
/ 28 февраля 2011

Я могу дать вам огромный общий обзор «чего нельзя», относящегося к вашему коду.

  • Вы правы в этом случае, если вы используете классы, «производные» от simple_instr, но выделают это неправильно, учитывая, что позже вы делаете оператор switch на основе типа.Оператор switch, основанный на типе (а не на состоянии), является антишаблоном.Вы должны вызывать некоторый виртуальный метод вашего базового класса.

  • Вы почти наверняка не хотите, чтобы ваш производный класс копировался из базового класса.Вы хотите построить его с параметрами для построения его базового класса.

  • Вам нужен вектор указателей базового класса?А для управления временем жизни возможно shared_ptr

  • const-правильность.Некоторые из ваших методов, таких как size (), должны быть константными.Для других вам могут потребоваться две перегрузки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...