Невозможно повторно использовать одну и ту же строку (массив символов) в C

Следующий код приводит к ошибке сегментации при попытке повторного использования строки.

for(i=0;i<input_len;i++){
        char *loc=(char*)calloc(sizeof(char)*2,0);

                int pointer = 0;
        while(pointer<3){
            int local_index = pointer+i;
            sprintf(loc,"%02x",input[local_index]&0xff);    
            strcat(stream_length_string, loc);
            pointer++;
        }
        local_length = strtol(stream_length_string, NULL, 16);
            i=(local_length+8);

        loc[0]= 0;
} 

Я пытаюсь использовать строку loc на каждой итерации, но на 2-й итерации возникает ошибка сегментации в операторе sprintf. Я предполагаю, что он как-то не может очистить содержимое loc и заполнить его заново.


c
person Ujjawal Sharma    schedule 05.08.2019    source источник
comment
Почему вы думаете, что это может быть segfaulting? Что получится, если выписать на бумаге значения pointer, local_index и i для каждой итерации и учесть, к какой памяти в результате пытается получить доступ код? Ошибки сегментации связаны с тем, что что-то непривилегированное (ваш код) пытается получить доступ к памяти, принадлежащей чему-то другому (en.wikipedia.org /wiki/Segmentation_fault)   -  person wally    schedule 05.08.2019
comment
calloc(x*2, 0) — как вы думаете, сколько байтов будет выделено?   -  person Aconcagua    schedule 05.08.2019
comment
Ре. мой предыдущий комментарий - я вспомнил, что пытался предложить - таблицы трассировки: bouraspage.com/repository/algorithmic-thinking/   -  person wally    schedule 05.08.2019
comment
Является ли размер input_len массива input[]? Если это так, то local_index может превышать его.   -  person mMy    schedule 05.08.2019
comment
справочная страница сообщает нам: man7.org/linux/man-pages/man3/calloc.3p.html. Вы не проверяете, является ли loc NULL.   -  person Gerhardh    schedule 05.08.2019
comment
У вас утечка памяти, вы больше нигде не free локируетесь. Почему бы вам не использовать вместо этого локальный массив (char loc[3];)?   -  person Aconcagua    schedule 05.08.2019
comment
Только оптимизация: цикл for был бы намного лучше...   -  person Aconcagua    schedule 05.08.2019
comment
Я не согласен с дубликатом; он покрывает только одну ошибку, но есть и другие...   -  person Aconcagua    schedule 05.08.2019
comment
В моем комментарии выше цитата отсутствовала: если nelem или elsize равно 0, то должен быть возвращен либо нулевой указатель, либо уникальное значение указателя, которое может быть успешно передано в free().   -  person Gerhardh    schedule 05.08.2019


Ответы (1)


Я предполагаю, что вы хотели, чтобы инструкция calloc выделила 2 символа для указателя loc. Но, как указал @Aconcagua, этого не происходит: второй параметр равен 0, поэтому фактически выделяется 0 памяти!

вы, вероятно, хотели сделать:

char *loc=(char*)calloc(2, sizeof(char));

Это выделит память для двух последовательных символов. Calloc изначально инициализирует всю выделенную память нулем, поэтому вам не нужно ничего делать для этого.

Тогда вы можете подумать, что 2 символа достаточно для вызова sprintf, который запрашивается для записи двузначного числа в этот указатель. Однако в C строки заканчиваются нулевым символом, и функция sprintf добавит его в конец. Следовательно, вам потребуется по крайней мере три символа, выделенных для указателя loc.

Теперь нулевой символ будет записан в область памяти, которая могла быть назначена другой переменной. Как именно это приводит к ошибке сегментации, будет очень специфичным для вашей ситуации.

Итак, чтобы исправить ваш код, строка распределения должна выглядеть так:

char *loc=(char*)calloc(3, sizeof(char));
person slingeraap    schedule 05.08.2019
comment
'Ваша инструкция calloc выделяет 2 символа для указателя loc' – нет, внимательно посмотрите на второй аргумент... Все еще хорошо замечено, что не резервируется место для завершающего нулевого символа.. . - person Aconcagua; 05.08.2019