Это покажет вам немного о том, что происходит:
#include <stdio.h>
#include <stdlib.h>
void dbg_print_array(unsigned sz, const int * array, const char * label) {
fprintf(stderr, "{%s:\t%p:\t", label, array);
while (sz--) {
fprintf(stderr, " %x ", *array++);
}
fprintf(stderr, "}\n");
}
int main()
{
int *d_array, number, divisor_count, i, size = 1;
char answer;
d_array = (int*) malloc(size * sizeof(int));
dbg_print_array(size, d_array, "Initial");
do
{
printf("\nEnter a number: ");
scanf("%d", &number);
divisor_count = 0;
for(i = 2; i < number; i++)
if (number % i == 0) divisor_count++;
if(divisor_count == 0)
{
int * p;
dbg_print_array(d_array, size, "pre-realloc");
p = realloc(d_array,(size + 1) * sizeof(int));
dbg_print_array(d_array, size+1, "post-realloc (d_array)");
dbg_print_array(p, size+1, "post-realloc (p)");
d_array[size - 1] = number;
size++;
}
printf("\nIs there another number? y/n ");
getchar();
answer = getchar();
} while (answer == 'y');
for(i = 0; i < size - 1; i++)
printf("\n%d", d_array[i]);
return 0;
}
Что касается того, почему эти данные перезаписываются так скоро, сказать сложно. Различные реализации распределения кучи могут вести себя по-разному для этого. Поскольку перераспределение выполняется такими маленькими шагами (массив увеличивается на 1 каждый раз), realloc будет вызываться часто.
Так как, хотя вы и я обычно можем думать о нераспределенном пространстве кучи как о неиспользованном, функции выделения и освобождения кучи сохраняют там некоторые данные, чтобы идти в ногу с вещами. Так как каждый вызов realloc считывает эти данные, и предоставленная программа записывает данные, которые, вероятно, realloc предполагает, принадлежат подпрограммам выделения кучи, тогда она может читать что-то, что эта программа перезаписала (каждый раз она записывает конец первоначально выделенного пространства через петлю). После прочтения этих поврежденных данных realloc
может принять решение на основе того, что оно прочитало, в результате чего кто знает, что. На этом этапе программы вы должны рассматривать каждое поведение как undefined , поскольку основные предположения, сделанные для нормальной работы, больше не действительны.
редактировать
Изучив выходные данные вышеприведенного кода, вы сможете определить, когда realloc
действительно возвращает другой указатель, чем тот, который был передан (я предполагаю, что в вашем примере, для вашего последнего целочисленного значения должно быть место) потому что malloc, вероятно, округлил до 16 байтов для первого выделения - также потому, что realloc
не abort
, вероятно, так как ему никогда не передавали недопустимый указатель).
Смежные post-realloc операторы печати будут иметь разные адреса (для них напечатано первое число), когда realloc
не вернет тот же указатель, который был передан.