Описание
Неправильный синтаксис членского размера массива с переменными границами происходит, когда вы не используете стандартный Синтаксис C, чтобы задать структуру с участником массива с переменными границами.
Начиная с C99 можно задать участника массива с переменными границами с незаданным размером. Например, desc
является участником массива с переменными границами в этом примере:
struct record {
size_t len;
double desc[];
};
До C99 вы можете использовать специфичные для компилятора методы, чтобы задать массивы с переменными границами. Например, вы использовали массивы единицы или нули размера:
struct record {
size_t len;
double desc[0];
};
Это использование несовместимо со стандартами C после C99.
Риск
Если вы задаете участников массива с переменными границами при помощи нулевого размера или один, ваша реализация зависима компилятором. Для компиляторов, которые не распознают синтаксис, массив int
размера, у каждого есть буфер для одной переменной int
. При попытке записать вне этого буфера, можно столкнуться с проблемами, происходящими от доступа к массиву за пределы.
Если вы используете стандартный Синтаксис C, чтобы задать участника массива с переменными границами, ваша реализация является портативной через все компиляторы, соответствующие стандарту.
Фиксация
Чтобы реализовать участника массива с переменными границами в структуре, задайте массив незаданного размера. Структура должна иметь одного участника помимо массива, и массив должен быть последним членом структуры.
Пример - участник массива с переменными границами, заданный с размером один
#include <stdlib.h>
struct flexArrayStruct {
int num;
int data[1];
};
unsigned int max_size = 100;
void func(unsigned int array_size) {
if(array_size<= 0 || array_size > max_size)
exit(1);
/* Space is allocated for the struct */
struct flexArrayStruct *structP
= (struct flexArrayStruct *)
malloc(sizeof(struct flexArrayStruct)
+ sizeof(int) * (array_size - 1));
if (structP == NULL) {
/* Handle malloc failure */
exit(2);
}
structP->num = array_size;
/*
* Access data[] as if it had been allocated
* as data[array_size].
*/
for (unsigned int i = 0; i < array_size; ++i) {
structP->data[i] = 1;
}
free(structP);
}
В этом примере участник массива с переменными границами data
задан со значением размера одного. Компиляторы, которые не распознают этот синтаксис, обрабатывают data
как размер один массив. Оператор structP->data[i] = 1;
может записать в data
вне первого участника массивов и вызвать за пределы проблемы массивов.
Исправление — использует стандартный синтаксис C, чтобы задать массив с переменными границами
Задайте участников массива с переменными границами с незаданным размером.
#include <stdlib.h>
struct flexArrayStruct{
int num;
int data[];
};
unsigned int max_size = 100;
void func(unsigned int array_size) {
if(array_size<=0 || array_size > max_size)
exit(1);
/* Allocate space for structure */
struct flexArrayStruct *structP
= (struct flexArrayStruct *)
malloc(sizeof(struct flexArrayStruct)
+ sizeof(int) * array_size);
if (structP == NULL) {
/* Handle malloc failure */
exit(2);
}
structP->num = array_size;
/*
* Access data[] as if it had been allocated
* as data[array_size].
*/
for (unsigned int i = 0; i < array_size; ++i) {
structP->data[i] = 1;
}
free(structP);
}