Что не так с realloc? - PullRequest
       8

Что не так с realloc?

1 голос
/ 10 сентября 2011

У меня есть следующий код, который вы можете попробовать использовать c99 filename.c; ./a.out

#include <stdio.h>
#include <stdlib.h>

typedef unsigned long long int se_t;  // stack element type

se_t stack_size = 0;
se_t *bottom_of_stack = NULL;
#define top_of_stack (bottom_of_stack + stack_size * sizeof(se_t))

#define stack_infix(op) stack_push(stack_pop() #op stack_pop())
#define do_times(x) for(int _i=0; _i<x; _i++)

void stack_push(se_t v) {
    bottom_of_stack = realloc(bottom_of_stack,
                              ++stack_size * sizeof(se_t));
    *top_of_stack = v;
}

void stack_print() {
    printf("stack(%d): \n", (int)stack_size);
    for(se_t *i = bottom_of_stack;
             i <= top_of_stack;
             i += sizeof(se_t)) {
        printf("%p: %d \n", (void*)i, (int)*i);
    }
}

int main() {
    int i = 2;
    do_times(3) {
        stack_push(i*=i);
        stack_print();
    }
}

Я перераспределяю стек каждый раз, когда что-то добавляю в него. Вот вывод (с моими комментариями):

stack(1): 
0x105200820: 0  // realloc successfully allocated some memory for the first time 
0x105200860: 4 
stack(2): 
0x105200820: 0  // extended the memory range without moving it somewhere else
0x105200860: 4 
0x1052008a0: 16 
stack(3): 
0x105200830: 0  // reallocated the memory to some other region (see the address) 
0x105200870: 0  // and failed for some reason to copy the old data!
0x1052008b0: 0  // why?!
0x1052008f0: 256 

Ответы [ 2 ]

4 голосов
/ 10 сентября 2011

В арифметике указателей уже используется sizeof (basetype).Когда вы делаете

#define top_of_stack (bottom_of_stack + stack_size * sizeof(se_t))

, вы фактически умножаете на sizeof (se_t) дважды.

, если bottom_of_stack имеет значение 0xF000 и stack_size равно 2, а sizeof (se_t) равно 0x10

bottom_of_stack + stack_size == 0xF020
bottom_of_stack + stack_size * sizeof (se_t) == 0xF400 /* or whatever */
2 голосов
/ 10 сентября 2011

Используйте это:

#define top_of_stack (bottom_of_stack + (stack_size - 1))

На самом деле вы сохраняете данные после конца выделенного пространства.

О, и измените эту строку тоже:

i += sizeof(se_t)) {

Должно быть:

i++) {

Из-за того, что pmg сказал об арифметике указателей.

...