Строка, выделенная с помощью malloc, недоступная после возврата функции - PullRequest
0 голосов
/ 03 мая 2018

Я столкнулся со странной ошибкой, и я не могу на всю жизнь разобраться в ней. У меня есть функция, которая декодирует массив байтов в строку на основе другой функции кодирования. Функция, которая декодирует, выглядит примерно так:

char *decode_string( uint8_t *encoded_string, uint32_t length,
    uint8_t encoding_bits ) {
        char *sequence_string;
        uint32_t idx = 0;
        uint32_t posn_in_buffer;
        uint32_t posn_in_cell;
        uint32_t encoded_nucleotide;
        uint32_t bit_mask;

        // Useful Constants
        const uint8_t CELL_SIZE = 8;
        const uint8_t NUCL_PER_CELL = CELL_SIZE / encoding_bits;

        sequence_string = malloc( sizeof(char) * (length + 1) );
        if ( !sequence_string ) {
            ERR_PRINT("could not allocate enough space to decode the string\n");
            return NULL;
        }
        // Iterate over the buffer, converting one nucleotide at a time.
        while ( idx < length ) {
            posn_in_buffer = idx / NUCL_PER_CELL;
            posn_in_cell = idx % NUCL_PER_CELL;
            encoded_nucleotide = encoded_string[posn_in_buffer];
            encoded_nucleotide >>= (CELL_SIZE - encoding_bits*(posn_in_cell+1));
            bit_mask = (1 << encoding_bits) - 1;
            encoded_nucleotide &= bit_mask;
            sequence_string[idx] = decode_nucleotide( encoded_nucleotide );
                // decode_nucleotide returns a char on integer input.
            idx++;
        }
        sequence_string[idx] = '\0';
        printf("%s", sequence_string);    // prints the correct string
        return sequence_string;
}

Ошибка в том, что указатель возврата, если я пытаюсь его напечатать, вызывает ошибку сегментации. Но вызов printf("%s\n", sequence_string) внутри функции напечатает все просто отлично. Если я вызываю функцию следующим образом:

const char *seq = "AA";
uint8_t *encoded_seq;
encode_string( &encoded_seq, seq, 2, 2);
char *decoded_seq = decode_string( encoded_seq, 2, 2);

if ( decoded_seq ) {
    printf("%s\n",decoded_seq);    // this crashes
    if ( !strcmp(decoded_seq, seq) ) {
        printf("Success!");
}

тогда он потерпит крах на отпечатке. Несколько замечаний, другие функции, кажется, все работают, я довольно тщательно их протестировал (т.е. decode_nucleotide, encode_string). Строка также печатается правильно внутри функции. Только после возврата функция перестает работать. Мой вопрос: что может привести к тому, что эта память станет недействительной, просто возвращая указатель из функции? Заранее спасибо!

1 Ответ

0 голосов
/ 03 мая 2018

Первое (и не столь важное, но) утверждение:

sequence_string = malloc( sizeof(char) * (length + 1) );

sizeof(char) по определению всегда == 1. поэтому утверждение становится:

sequence_string = malloc(length + 1); 

В этом разделе вашего поста:

char *decoded_seq = decode_string( encoded_seq, 2, 2);

... так как я не вижу вашей реализации decode_string, я могу только делать предположения о том, как вы проверяете его вывод перед его возвратом. Однако я понимаю, что вы ожидаете, что возвращаемое значение будет содержать значения, которые будут допустимым содержимым строки C. Я также могу предположить , что, поскольку вы работаете с кодированием и декодированием, тип вывода скорее всего unsigned char. Если я прав, то допустимый диапазон символов для типа вывода беззнаковый символ - 0-255 .

Вы не проверяете вывод перед отправкой значения в оператор printf. Если значение по адресу памяти decoded_seq окажется 0, (в диапазоне unsigned char) ваша программа будет аварийно завершена. Строковые функции плохо работают с нулевыми указателями.

Вы должны проверить возвращение _decode_string_, отправив его на printf

char *decoded_seq = decode_string( encoded_seq, 2, 2);
if(decoded_seq != NULL)
{
    ...
...