Segfault при n-м взаимодействии через std::map

Решение. См. пост Бо Перссона и мой комментарий ниже.

Я получаю ошибку сегментации с моей картой. Что меня смущает, так это то, что итерации n-1 по ключам работают, но затем возникают ошибки seg на n-й итерации. Чтобы еще больше запутать, значение ключа, на котором произошел сбой сегмента итерации, находится (с помощью итератора) в предыдущей итерации и даже раньше в коде.

Я попытался профилировать ошибку seg с помощью valgrind, однако я получаю бесконечный цикл сообщения «сигнал 11 отбрасывается из потока 0». Следовательно, valgrind не очень полезен.

Карта с разломом сегмента называется site_depths. Вот как вставляются значения:

map<string,unsigned short*> site_depths;
map<string,unsigned int>::iterator it;
map<string,unsigned short*>::iterator insert_it;
unsigned int size = 0;
string key = "";

// go through each key pair of CHROM_SIZES to build the site_depth map
for (it=CHROM_SIZES.begin(); it != CHROM_SIZES.end(); it++) {
    key = it->first;
    size = it->second;

    unsigned short *array = new unsigned short[size];

    insert_it = site_depths.end();
    site_depths.insert(insert_it, pair<string,unsigned short*>(key,array));
}

Я проверил, чтобы убедиться, что все добавленные значения работают. И ключ, и размер выводятся на консоль.

Сразу после этого я проверяю, работают ли find() и [] access со значением ключа, которое вызывает ошибку seg (это также работает):

cout << "schill found: " << site_depths.find("lcl_NM_000999")->first << endl;
unsigned short* test_array = site_depths["lcl_NM_000999"];

Затем, когда я разбираю текстовый файл, он выдает ошибку при поиске () или, если я рекомендую это, при доступе []:

            string line;
            string chromosome;
            unsigned int start;
            unsigned int end;
            unsigned int i;
            char* values[3];
            unsigned short* sites;
            map<string,unsigned short*>::iterator iter_end = site_depths.end();

        while (getline(in,line)) {
            //use C strtok to tokenize the line
            char cstr[line.size()+1];
            strcpy(cstr,line.c_str());

            char *pch = strtok(cstr, "  ");

            // tokenize three columns
            for (i=0; i<3 || pch != NULL; i++) {
                values[i] = pch;
                pch = strtok(NULL, "    ");
            }

            chromosome = values[0];
            start = atoi(values[1])-1;  //must subtract 1 to correspond to 0 index
            end = atoi(values[2])-1;

            // get appropriate array pointer
            if (site_depths.find(chromosome) == iter_end) {
                cerr << "WARNING: Chromosome name in Input file does not match .len file." << endl;
                cerr << " Exiting script." << endl;
                exit(EXIT_FAILURE);
            }
            sites = site_depths[chromosome];

            // increment over range
            for (i=start; i<end; i++) {
                sites[i]++;
            }
        }

Случай, когда он segfaults, связан с ключом «lcl_NM_000998» при попытке найти ключ «lcl_NM_000999». Это не имеет смысла, поскольку предыдущая итерация getline() находит значение ключа «lcl_NM_000998». Я проверил, чтобы убедиться, что это так, вручную перебирая карту.

Я проверил, чтобы убедиться, что мой предыдущий код не был ошибочным в предыдущем коде, но токенизация выглядит нормально. Мой код всегда segfaults в этом месте в моем тестовом примере. Есть у кого идеи!?


person Ian    schedule 21.07.2011    source источник
comment
Условие в цикле for i<3 || pch != NULL кажется мне подозрительным... не должно ли оно быть i<3 && pch != NULL?   -  person Naveen    schedule 21.07.2011
comment
Вы правы, однако я все еще получаю ошибку seg. Вывод проанализированных значений показывает, что они действительны (особенно хромосома).   -  person Ian    schedule 21.07.2011


Ответы (1)


Это не просто тест на присутствие

unsigned short* test_array = site_depths["lcl_NM_000999"];

но также вставляет узел в site_depths, но с нулевым указателем в элементе second.

Код также считает, что start и end всегда находятся в пределах диапазона размера массива, заданного size. Не мешало бы это подтвердить!

person Bo Persson    schedule 21.07.2011
comment
отличный момент. Смотрите обновление. Сначала я проверил с помощью find(), и он все еще работает. Спасибо за совет по проверке начала и конца. - person Ian; 21.07.2011
comment
проверка диапазона решила проблему. Видимо, я писал за пределами отведенного мне места. Похоже, второй входной файл, в котором указаны размеры, был неправильным. Спасибо! - person Ian; 22.07.2011