#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.