Копировать std::list в std::vector, пропуская элементы

Я столкнулся с довольно странным исключением при запуске кода C++ в моем приложении Objective-C. Я использую libxml2 для чтения файла XSD. Затем я сохраняю соответствующие теги как экземпляры класса Tag в std::list. Затем я копирую этот список в std::vector, используя итератор в списке. Однако время от времени некоторые элементы списка не копируются в вектор. Любая помощь будет принята с благодарностью.

 printf("\n length list = %lu, length vector = %lu\n",XSDFile::tagsList.size(), XSDFile::tags.size() );
std::list<Tag>::iterator it = XSDFile::tagsList.begin();
//result: length list = 94, length vector = 0

/*
for(;it!=XSDFile::tagsList.end();++it)
{
    XSDFile::tags.push_back(*it); //BAD_ACCESS code 1  . .  very bizarre . . . . 25
}

 */
std::copy (XSDFile::tagsList.begin(), XSDFile::tagsList.end(), std::back_inserter (XSDFile::tags));

printf("\n Num tags in vector = %lu\n", XSDFile::tags.size());

if (XSDFile::tagsList.size() !=  XSDFile::tags.size())
{
    printf("\n length list = %lu, length vector = %lu\n",XSDFile::tagsList.size(), XSDFile::tags.size() );
    //result: length list = 94, length vector = 83
}

person Jays    schedule 31.10.2013    source источник
comment
Что является исключением?   -  person trojanfoe    schedule 31.10.2013
comment
Я думаю, что класс XSDFile реализует свой собственный итератор, поэтому он может пропустить итерацию некоторых элементов по назначению.   -  person nio    schedule 31.10.2013
comment
Почему бы просто не: std::copy (XSDFile::tagsList.begin(), XSDFile::tagsList.end(), std::back_inserter (XSDFile::tags));?   -  person John Dibling    schedule 31.10.2013
comment
@JohnDibling Да, это лучше, однако код ОП тоже должен работать.   -  person trojanfoe    schedule 31.10.2013
comment
@trojanfoe: Вот почему я только прокомментировал, а не ответил.   -  person John Dibling    schedule 31.10.2013
comment
Вы уверены, что XSDFile::tags пусто перед запуском этого кода?   -  person trojanfoe    schedule 31.10.2013
comment
На самом деле исключение возникает позже в моем коде из-за отсутствия тегов в массиве. Приведенный выше код работает нормально. И здесь XSDFile::tags создается только экземпляр, поэтому он должен быть пустым. XSDFile — это класс, который я создал для разбора XSD с помощью libxml2.   -  person Jays    schedule 31.10.2013
comment
Я только что попробовал std::copy, и результат тот же. Первые 4 раза я запускал код, он работал, но на пятый количество тегов в векторе было 83, а размер списка 94.   -  person Jays    schedule 31.10.2013
comment
Можете ли вы изменить вывод ошибки, чтобы он фактически печатал значения размера в этот момент? Совпадают ли они, когда у вас появляется ошибка позже?   -  person Dave S    schedule 31.10.2013
comment
Что еще более важно, распечатайте значения до и после запуска кода.   -  person trojanfoe    schedule 31.10.2013
comment
Раньше: список длин = 94 вектора длин = 0   -  person Jays    schedule 31.10.2013
comment
После: список длин = 94 длины вектора 83. Эти длины одинаковы, когда позже в коде появляются ошибки. Однако в большинстве случаев я получаю правильный результат, и длина вектора соответствует длине списка.   -  person Jays    schedule 31.10.2013
comment
@Jays: Если это непоследовательно, то я подозреваю, что это ошибка вне кода, который вы показываете. Я бы порекомендовал такой инструмент, как valgrind   -  person Dave S    schedule 31.10.2013
comment
Вальгринд. . никогда об этом не слышал. Я попробую. Спасибо.   -  person Jays    schedule 31.10.2013
comment
В качестве окончательного предположения, делает ли что-нибудь деструктор/конструктор Tag с любым из этих двух контейнеров? Я спрашиваю, потому что кажется, что эти контейнеры являются статическими членами, так что это возможно.   -  person Dave S    schedule 31.10.2013
comment
Tag — это просто базовый класс, в котором нет ничего, кроме сеттеров и геттеров. Он ничего не делает ни с одним из контейнеров.   -  person Jays    schedule 31.10.2013


Ответы (1)


Я нашел проблему. Память была повреждена, что привело к повреждению std::list во время синтаксического анализа XSD. Я разбираю XSD с помощью функции start_element.

xmlSAXHandler handler = {0};
handler.startElement = start_element;

Я использовал защиту malloc в xcode, чтобы определить использование освобожденной памяти. Он указал на строку:

std::strcpy(message, (char*)name);

Поэтому я удалил malloc (фактически прокомментированный в коде), и это сработало. Теперь std::vector последовательно копирует все 94 элемента списка. Если у кого-то есть объяснение, почему это сработало, было бы здорово.

static void start_element(void * ctx, const xmlChar *name, const xmlChar **atts)
{    
// int len = strlen((char*)name);

//    char *message = (char*)malloc(len*sizeof(char));
//    std::strcpy(message, (char*)name);

if (atts != NULL)
{
 //   atts[0] = type
 //   atts[1] = value

 //   len = strlen((char*)atts[1]);
 //   char *firstAttr = (char*)malloc(len*sizeof(char));
 //   std::strcpy(firstAttr, (char*)atts[1]);


     if(strcmp((char*)name, "xs:include")==0)
     {   
         XSDFile xsd;
         xsd.ReadXSDTypes((char*)atts[1]);
     }

     else if(strcmp((char*)name, "xs:element")==0)
     {
         doElement(atts);
     }


     else if(strcmp((char*)name, "xs:sequence")==0)
     {
         //set the default values
         XSDFile::sequenceMin = XSDFile::sequenceMax = 1;

         if (sizeof(atts) == 4)
         {
            if(strcmp((char*)atts[3],"unbounded")==0)
                XSDFile::sequenceMax = -1;

             int i = 0;
             while(atts[i] != NULL)
             {
                 //atts[i] = name
                 //atts[i+i] = value

                 std::string name((char*)atts[i]);
                 std::string value((char*)atts[i+1]);

                 if(name=="minOccurs")
                     XSDFile::sequenceMin = (atoi(value.c_str()));
                 else if(name=="maxOccurs")
                     XSDFile::sequenceMax = (atoi(value.c_str()));

                 i += 2;
             }

         }

     }
}

//free(message);
}
person Jays    schedule 01.11.2013