#c #malloc
#c #malloc
Вопрос:
При использовании я получаю ошибку сегментации strncpy
, и я не могу понять, как это исправить.
Вот мой rectangle.h
файл. Это всего лишь заголовочный файл.
#define NAMESIZE 20
struct point {
int x;
int y;
};
struct rectangle {
struct point upperleft;
struct point lowerright;
//char label[NAMESIZE 1];
char *label;
};
struct point *create_point(int x, int y);
struct rectangle *create_rectangle(struct point ul, struct point lr,
char *label);
int area1(struct rectangle r);
int area2(struct rectangle *r);
void change_label(struct rectangle *r, char *newlabel);
void broken_change_label(struct rectangle r, char * newlabel);
void print_rectangle(struct rectangle *r);
Это мой rectangle.c
файл. Я просто собираюсь показать одну функцию из него:
/* create_rectangle динамически выделяет память для хранения прямоугольника, присваивает ему * начальные значения и возвращает указатель на вновь созданный прямоугольник. */
struct rectangle *create_rectangle(struct point ul, struct point lr,
char *label) {
struct rectangle *r = malloc(sizeof(struct rectangle));
/* TASK 1: fill in the rest of this function */
r->upperleft = ul;
r->lowerright = lr;
r->label = malloc(strlen(label) * sizeof(char));
strncpy(r->label, label, strlen(label) 1);
return r;
}
В приведенном выше коде я использую malloc
, чтобы выделить достаточно места для указателя метки.
Когда я запускаю tester.c
приведенную ниже программу, я получаю ошибку ошибки сегментации (из-за strncpy
).
int main(void) {
char *str1 = "Big rectangle";
char *str2 = "Square";
struct point *p1 = create_point(10, 10);
struct point *p2 = create_point(100, 100);
struct rectangle *r1 = create_rectangle(*p1, *p2, str1);
print_rectangle(r1);
printf(" expecting: (10, 10) (100, 100) Big rectanglen");
free(p2);
p2 = create_point(20, 20);
struct rectangle r2;
strncpy(r2.label, str2, NAMESIZE); //GETTING SEGMENTATION FAULT DUE TO THIS LINE
}
Я подозреваю, что я получаю ошибку ошибки сегментации, потому что я делаю strncpy
это напрямую r2.label
. Я подозреваю, что из-за того, что я не выделяю никакого пространства char *label
в структуре rectangle, я получаю ошибку ошибки сегментации. Но когда я пишу
char *label = malloc(sizeof(NAMESIZE) * sizeof(char));
Я получаю сообщение об ошибке:
error: expected ';' at end of declaration list` error.
Комментарии:
1. Внимательно
strncpy
подумайте, действительно ли это правильный инструмент для этой работы. Это не просто «безопаснее»strcpy
. См. Мою разглагольствование по этой теме , а также вопрос 13.2 из часто задаваемых вопросов comp.lang.c . (Я не предполагаю, что это является причиной проблемы, которую вы видите.)2.
malloc(sizeof(NAMESIZE) * sizeof(char))
— что?NAMESIZE
это int, так что, вероятно, это выделяет 4 байта.
Ответ №1:
strncpy(r2.label, str2, NAMESIZE);
Вы пытаетесь выполнить запись в r2.label
, который является указателем, которому не было выделено никакого места.
И будьте осторожны с кодом, который вы выделили пространство:
r->label = malloc(strlen(label) * sizeof(char));
strlen(label)
недостаточно, строка должна заканчиваться нулем.
Комментарии:
1. Что произойдет, если строка не завершается нулем?
2. Тогда это не строка. Значение string таково: серия символов, за которыми следует нулевой терминатор.
Ответ №2:
Этот код:
r->label = malloc(strlen(label) * sizeof(char));
strncpy(r->label, label, strlen(label) 1);
должно быть:
r->label = malloc( strlen(label) 1 );
strcpy( r->label, label );
- Вам нужно выделить место для нулевого терминатора.
sizeof(char)
всегда1
strcpy
Функция завершается после записиstrlen(label) 1
байтов, поэтому пытаться использовать ее излишнеstrncpy
.
strncpy
в целом довольно опасно, потому что иногда он не выводит строку; мой совет — никогда не использовать его.
Далее вниз,
strncpy(r2.label, str2, NAMESIZE);
неверно, потому r2.label
что в настоящее время является диким указателем. Вам также необходимо выделить память таким же образом:
r2.label = malloc( strlen(str2) 1 );
strcpy( r2.label, str2 );
Комментарии:
1. Есть ли какой-либо способ зарезервировать место для строкового литерала метки в самой структуре? Что-то вроде: char * label = malloc(sizeof(NAMESIZE) 1);
2. Да, измените на
char label[NAMESIZE 1];
3. Прекратите писать
sizeof(NAMESIZE)
.NAMESIZE
есть20
.sizeof(NAMESIZE)
означаетsizeof(20)
, то есть количество байтов, необходимых для хранения int20
. То естьsizeof(int)
, это 4 или 8 в обычных системах.
Ответ №3:
Похоже, как вы сказали, вы не выделяете никакой памяти для своего char* label
.
Сделать:
r2.label = malloc(sizeof(NAMESIZE) * sizeof(char));`
Ответ №4:
Вы malloc
strlen(label)
вводите байты для метки create_rectangle
, затем копируете в strlen(label) 1
байтах. Обратите внимание, что если новая метка, в которую вы копируете, длиннее, вы переполните это выделение. Но, как указывает @YuHao, это не имеет значения, потому что вы никогда не инициализировали ни одно из полей r2
(в частности, label
).
Ответ №5:
r->label = malloc(strlen(label) * sizeof(char));
Вы неправильно распределяете завершающий символ, он должен быть
r->label = malloc((strlen(label) 1) * sizeof(char));