Objective-C EXEC_BAD_ACCESS при использовании массивов гибкой длины
Я провел некоторое тестирование поведения, которое обнаружил, и мне было интересно, может ли кто-нибудь помочь мне понять, что происходит.
У меня есть структура под названием myStruct
это выглядит так:
typedef struct {
int size;
float floats[];
} myStruct;
И я запускаю этот код на нем:
int main () {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSArray *a = [[NSArray alloc] initWithObjects:@"0.2", @"0.5", @"0.5", nil];
NSLog(@"%@", a);
myStruct my;
my.size = a.count;
my.floats[0] = [[a objectAtIndex:0] floatValue];
my.floats[1] = [[a objectAtIndex:1] floatValue];
my.floats[2] = [[a objectAtIndex:2] floatValue];
NSLog(@"{ %lf, %lf, %lf }", my.floats[0], my.floats[1], my.floats[2]);
[a release];
[pool drain];
return 0;
}
Работает нормально. Однако, когда я изменяю объявление структуры на это:
typedef struct {
float myVar;
int size;
float floats[];
} myStruct;
Я получаю EXEC_BAD_ACCESS, когда я вызываю линию [a release]
,
Может ли кто-нибудь помочь мне понять, что здесь происходит?
2 ответа
Вы должны фактически выделить место для вашего гибкого члена массива! Эта строка:
myStruct my;
Достаточно места для стека size
(или же myVar
а также size
из вашего второго примера). Похоже, что в вашем неудачном случае вы перезаписываете a
в стеке, но на самом деле оба случая неверны. Чтобы решить вашу проблему, вам нужно выделить место для floats[]
член структуры:
myStruct *my = malloc(sizeof(myStruct) + a.count * sizeof(float));
Не забудь free()
это когда вы закончите!
Быстрый пример - эта программа:
#include <stdio.h>
typedef struct {
float myVar;
int size;
float floats[];
} myStruct;
int main(int argc, char **argv)
{
printf("%zu\n", sizeof(myStruct));
return 0;
}
и его вывод:
$ make testapp
cc testapp.c -o testapp
$ ./testapp
8
Вы не выделяете память для своих поплавков - я удивлен, что это не даст сбой раньше!
Вам нужно распределить память для указателя с плавающей точкой []?
После быстрого теста я получаю EXC_BAD_ACCESS для обоих определений myStruct:)