realloc не работает в функции - PullRequest
1 голос
/ 02 ноября 2011
int *f, *l;

int main(){
    int *a;
    a = calloc(1, sizeof(int));
    f = l = a;
    put(&a, 1);
    put(&a, 3);
    put(&a, 2);
    _getch();
    return 0;
}

void put(int **a, int d){
    printf("--%d--", sizeof(*a));          //always == 4
    void *tmp = (int *)realloc(*a, sizeof(*a) + sizeof(int)); 
    if (temp)                              //allocated succesfully
        *a = temp;
    else
        printf("Allocating a failed");
    l++;
}

Я пытаюсь создать модель очереди на основе указателей int.

Я немного исправил выборку.Но все равно не получилось.Не могли бы вы помочь?

Ответы [ 7 ]

1 голос
/ 02 ноября 2011

sizeof(a) - это размер указателя, а не то, на что указывает a.

1 голос
/ 02 ноября 2011

В C нет способа узнать размер массива, на который ссылается указатель:

int a[25]; // Known size
int *b = a; // Unknown size

, поэтому sizeof() просто печатает размер указателя, который составляет 4 байта на 32-битной платформе.

Если вам нужен размер, выделите структуру следующим образом:

struct Mem {
    int size;
    int a[1];
}

Используйте sizeof(struct Mem) + sizeof(int) * amount, чтобы определить, сколько памяти выделить, назначьте ее указателю. Теперь вы можете использовать память с ptr->a[x].

Обратите внимание, что он выделит немного больше памяти, чем необходимо (обычно 4 байта), но этот подход работает с различными выравниваниями, размерами указателя и т. Д.

1 голос
/ 02 ноября 2011

a является указателем типа int (int *), поэтому его размер (4 байта (на вашем компьютере)) следует отслеживать за размером выделенной памяти.

Например:

int *f, *l;

int main(){
    int *a;
    size_tasize = 0;
    a = calloc(1, sizeof(int));
    f = l = a;
    asize = sizeof(int);
    put(a, 1, &asize);
    put(a, 3, &asize);
    put(a, 2, &asize);
    _getch();
    return 0;
}

void put(int *a, int d, size_t * asize){
    printf("--%d--\n", asize);        //always == 4
    void *tmp = (int *)realloc(a, *asize + sizeof(int));
    (*asize) += 4;
    if (tmp)
        a = tmp;      //allocated succesfully
    else
        printf("Reallocating of 'a' size %d failed\n", asize);
    l++;
}
0 голосов
/ 02 ноября 2011

Вся концепция работает не так, как вам бы.

  • Материал sizeof a не работает так, как вы собираетесь.
  • Перераспределение само по себе неверно, так как вы не возвращаете новый адрес вызывающей стороне.
  • У вас нет информации о длине ваших данных.

Я бы предложил следующее:

struct memblock {
    unsigned int alloced;
    unsigned int len;
    int * data;
}

// in order to prealloc
char add_realloc(struct memblock * mb, unsigned int add) {
    add += mb->alloced;
    int * tmp = realloc(mb->data, sizeof(*mb) + add * sizeof(*(mb->data)));
    if (!tmp) return 0;
    mb->data = tmp;
    mb->alloced = add;
    return 1;
}

char put(struct memblock * mb, int d) {
    if (mb->len == mb->alloced) {
        // realloc
        if (!add_realloc(mb, 1)) return 0;
    }
    mb->data[mb->len++] = d;
    return 1;
}

int main(){
    struct memblock a = {} // init with all zeros.
    // Calling realloc() with a NULL pointer is like malloc().

    // we put 3 values. Prealloc for not to have to realloc too often.
    if (add_realloc(&a, 3) {
        // now we are safe. Don't check the return values - it is guaranteed to be ok.
        put(&a, 1);
        put(&a, 3);
        put(&a, 2);
    }

    return 0;
}
0 голосов
/ 02 ноября 2011

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

0 голосов
/ 02 ноября 2011

Вместо выполнения

if (tmp)
    a = tmp;

верните tmp и присвойте его a в основном.

0 голосов
/ 02 ноября 2011

Вы изменяете локальную переменную a внутри функции, а не переменную a в своей основной функции.Вам нужно либо вернуть новое значение a из put (), либо передать указатель на ваш указатель (int ** a), чтобы изменить его.

Например:

int *put(int *a, int d);

int main(){
    int *a;
    a = calloc(1, sizeof(int));
    a = put(a, 1);
    ...
}

int *put(int *a, int d){
    void *tmp = (int *)realloc(a, sizeof(a) + sizeof(int));
    if (tmp)
        a = tmp;      //allocated succesfully
    else
        printf("Reallocating of 'a' size %d failed\n", sizeof(a));
    return a;
}

sizeof (a) всегда будет возвращать 4 в вашем случае.Он возвращает размер указателя, а не размер выделенной памяти, на которую указывает указатель.

...