Настройка поля char* в структуре, язык C

#c

Вопрос:

Предположим, у меня есть следующая структура:

 typedef struct body{
    char* text;
} body_t;
 

Я хочу написать функцию, которая позволяет мне устанавливать и получать текст структуры тела в строку, которую я передаю. Я написал следующие функции:

 void body_set_text(body_t* body, char* text){
    if(body->text != NULL){
        free(body->text);
    }
    body->text = text;
}

char* body_get_text(body_t* body){
    return body->text;
}
 

Текстовое поле в теле может содержать несколько символов или один символ. Я хочу использовать функцию body_set_text для изменения текста с учетом ввода пользователем одного символа. Я написал следующую функцию:

 void process_player_entry(body_t* body, char c){
    char* new_char = malloc(sizeof(char));
    snprintf(new_char, "%c", c);
    body_set_text(body, new_char);
}
 

Однако это приводит к ошибке переполнения буфера кучи. Кто-нибудь знает, что я делаю не так?

Комментарии:

1. 2 — м аргументом snprintf должен быть размер.

2. Для хранения строки длиной N необходимо выделить буфер размером не менее N 1. Буфер размером 1 не может содержать строку, кроме тривиальной строки длиной 0.

3. free(NULL) это совершенно безопасно. Нет никакого реального смысла проверять, является ли указатель ненулевым перед вызовом free .

4. Обратите внимание , что если вы позвоните body_set_text(something, "hello") , то следующий звонок с body_set_text(something, ...) треском провалится, потому что вы не сможете free("hello") .

Ответ №1:

В вашем коде есть несколько других проблем, на которые указывают другие люди в комментариях. Однако вы можете заставить его работать, приведя snprintf(3) правильные аргументы:

 // function signature
int snprintf(char *str, size_t size, const char *format, ...);

// the second argument is "size"

void process_player_entry(body_t* body, char c){
    // change here to "2", so you have space for the character and
    // the NULL terminator
    char* new_char = malloc(2);
    // so changing here should be fine
    snprintf(new_char, 1, "%c", c);
    body_set_text(body, new_char);
}
 

Из руководства:

Функции snprintf() и vsnprintf() записывают не более байтов размера (включая завершающий нулевой байт (»)) в str.