Почему мое строковое назначение вызывает ошибку сегментации? - PullRequest
2 голосов
/ 30 августа 2011

Я пытался устранить распространенные причины ошибок seg, таких как разыменование нулевого указателя, но я в тупике.Эта ошибка не появляется на моей тестовой машине в режиме отладки, но появляется на моей рабочей машине после компиляции релиза.Оба установлены в / O0, чтобы исключить это как возможность.Когда я закомментирую строковое назначение, ошибка сегмента исчезнет, ​​теперь мне просто нужно понять, что происходит, чтобы я мог это исправить.

Может быть что-то более очевидное, но дополнительное осложнение заключается в том, что этот кодвызывается приложением режима ядра, и единственные инструкции, которые я получаю от поставщика по написанию безопасного кода для системы, это «каждая функция, которая требует чего-либо от операционной системы или должна ждать чего-либо от ОС, не будет работать» (дословно).

union {
    REAL_T real[8];
    char   byte[64];
} fileName;

void transferFilenames () {
    string tempname;

    // This is from an api I must use, it retrieves values from NVRAM on
    // an accessory board.  Specifically it will return 8 REAL_T values
    // and store them starting at &filename.real[0], inp/outpArray are 
    // globals defined elsewhere.
    inpArray.I7_ARRAY.INDEX = 2903;
    inpArray.I7_ARRAY.LEN = 8;
    inpArray.I7_ARRAY.Z_PAR_PTR = &fileName.real[0];
    b_array ( READ_CYCLE_PARAMS, &status, &inpArray, &outpArray );

    // if status != 0, there was an error
    if ( status == 0 ) {
        // there is no guarantee of being null terminated
        fileName.byte[63] = 0;

        /* This test code didn't fix the problem
        int i;
        char myStr[64];
        for ( i = 0; i < 64; i++ )
            myStr[i] = fileName.byte[i];
        if ( myStr[0] != '\0' )
            string mystring( myStr ); // seg fault
        */
        tempname.assign( fileName.byte ); // Throws seg fault
        // tempname.assign( &fileName.byte[0] ); // try to be more explicit

        // controlBlock is a global class defined elsewhere
        controlBlock->setFileName ( tempname, ISINPUT);
    } else {
        controlBlock->setFileName( "BAD", ISINPUT );
    }
    return;
}

Когда я перегрузил свой блок управления, чтобы получить символ * напрямую controlBlock->setFileName( &fileName.byte[0] ), и полностью удалил строковое назначение, ошибка сегментации исчезла.Все, что делает перегрузка, это присваивает char * локальной строке и вызывает обычный метод.

Чего мне не хватает за кулисами?

1 Ответ

3 голосов
/ 30 августа 2011

Возможно, проблема не в вызове tempname.assign().Конвейерная передача может привести к несколько ошибочным сообщениям о том, где на самом деле лежит демон.Это утверждение заставляет меня думать, что демон лежит в другом месте:

Когда я перегрузил свой управляющий блок, чтобы взять char * непосредственно controlBlock-> setFileName (& fileName.byte [0]), и полностью удалил строковое назначениеошибка сегментации исчезла.

Вы передаете std::string в setFileName в одном случае, char* в другом.Попробуйте заменить

controlBlock->setFileName ( tempname, ISINPUT);

на

controlBlock->setFileName ( tempname.c_str(), ISINPUT);

Добавление
Проблема может быть связана с использованием std::string, точка.std::string::assign() вызовет malloc, если зарезервированный размер слишком мал.Создание зарезервированного размера достаточно большим может не сработать;это может просто вставить вызов malloc в конструктор.Использование чего-то, что выделяет память динамически, не согласуется с пунктом , каждая функция, которая требует чего-либо от операционной системы или должна ждать чего-либо от ОС, не будет работать .

На самом деле,этот пункт вполне может исключить использование огромных кусков библиотеки C ++ на этом компьютере.Библиотека C ++ довольно свободна в отношении выделения и освобождения памяти, и std::string делает это много.

...