2013-12-07 3 views
2

Я изучаю C и пытаюсь построить динамический массив. Я нашел отличный учебник по этому вопросу, но я не понимаю его полностью. Код у меня сейчасДоступ к элементу динамического массива C

typedef struct{ 
    int size; 
    int capacity; 
    char *data; 
}Brry; 

void brry_init(Brry *brry){ 
    brry->size = 0; 
    brry->capacity = 2; 
    brry->data = (char *)calloc(brry->capacity, sizeof(char)); 
} 

void brry_insert(Brry *brry, char value){ 
     brry->data[brry->size++] = value; //so do check here if I have enough memory, but checking something out 
} 

int main(void){ 
    Brry brry; 
    brry_init(&brry); 

    for (int i = 0; i < 3; i++) { 
     brry_insert(&brry, 'a'); 
    } 

    printf("%c\n", brry.data[2]); 
    return 0; 
} 

В моей основной функции добавить 3 элемента в массиве, но он выделяется только 2. Но когда я печатаю это работает нормально? Я ожидал, что какая-то странная ценность будет напечатана. Почему это или я делаю что-то неправильно?

+1

Обратите внимание, что 'brry.data [3]' - это 4-й элемент. – Novak

+0

Извините, скопируйте полученную ошибку – Haagenti

+0

Это [неопределенное поведение] (http://stackoverflow.com/a/367662/1113392) – A4L

ответ

3

Вы пишете в буфер, на который вы не выделили достаточное количество памяти. То, что он работает, не гарантируется.

Теперь вы пытаетесь прочитать из некоторого значения нежелательной памяти в памяти, кто знает, что иногда приводит к ошибке сегментации, а иногда вам повезло и получить какое-то нежелательное значение, и это не segfault.

Запись в мусорную память вызовет неопределенное поведение, поэтому лучше смотреть ее. Если вы действительно ошибаетесь, это почти всегда будет segfault, сокращение от ошибки сегментации. Читайте дальше here.

Технический для того, что вы делаете, прочитывая за границами массива, называется детекцией указателя. Вы также можете узнать больше об этом here.

+0

Неверный путь. Если вам повезет, вы получите ошибку seg и знаете, что вы выросли вместо того, чтобы «это работает» на данный момент, и у кого-то в пути есть какая-то фатальная ошибка, которая потенциально может вызвать у компании миллионы долларов убытков из-за потери заработной платы, расходов на ремонт/редизайн и т. д. – ciphermagi

+0

@JonahNelson Да, иногда вам повезет узнать. Но просто давайте надеяться, что OP что-то узнает от него. – edwardmp

1

Да, вы действительно пишете третий элемент массива из двух элементов. Это означает, что ваша программа будет демонстрировать неопределенное поведение, и у вас нет гарантии того, что произойдет. В вашем случае вам повезло, и программа «работала», но вам не всегда может быть так повезло.

1

Попытка прочитать/записать за конец массива приводит к неопределенному поведению. То, что происходит, зависит от нескольких факторов, которые вы не можете предсказать или контролировать. Иногда, похоже, он будет читать и/или писать успешно, не жалуясь. В других случаях это может привести к ужасному и эффективному сбою вашей программы.

Критически важно то, что вы никогда не должны пытаться использовать или полагаться на неопределенное поведение. К сожалению, общая ошибка новобранец заключается в том, что он всегда будет работать, потому что один тест оказался успешным. Это определенно не так, и это рецепт катастрофы рано или поздно.

Смежные вопросы