ошибка: "освобождаемый указатель не был выделен" в c - PullRequest
3 голосов
/ 02 апреля 2012

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

здесьмоя структура без реального указателя внутри:

 typedef struct{
        int frame; 
        double timestamp; 
        int identifier; 
        int state; 
        int unknown1; 
        int unknown2; 
        mtVector normalized;
        float size; 
        int unknown3;
        float angle; 
        float majorAxis;
        float minorAxis;
        mtVector unknown4; 
        int unknown5[2]; 
        float unknown6; 
    }Touch;

основная функция barebone:

int main(){
    Touch *myTouch = NULL;
    int inputCounter = 0;
    //whenever  a touch is recognized:
    ...
    myTouch = (Touch*)realloc(myTouch,sizeof(Touch)*(inputCounter++));
    ...
    // everything works fine until:
    freeTouch(myTouch);
}

void freeTouch(Touch *f){
    if(f != NULL){
        free(f);
        f = NULL;
    }
}

кто-нибудь получил идею?

Ответы [ 3 ]

3 голосов
/ 02 апреля 2012

f является локальной переменной.free(f) повлияет на выделенную память, но f = NULL не повлияет на myTouch в freeTouch(myTouch);.

Попробуйте вместо этого

void freeTouch(Touch **f){
    if(*f != NULL){
        free(*f);
        *f = NULL;
    }
}

и используйте freeTouch(&myTouch).

2 голосов
/ 02 апреля 2012

У вас там две проблемы.Во-первых, это не очень хорошая идея явно приводить возвращаемое значение из malloc или realloc.Это может вызвать проблемы, если вы забудете включить для него прототип / заголовок.

Во-вторых, освобождение f внутри функции освобождает локальную копию.До тех пор, пока C не получит ссылки, есть две возможности.Сначала передайте указатель на указатель и используйте это:

void freeTouch (Touch **pF){
    if (*pF != NULL){
        free (*pF);
        *pF = NULL;
    }
}
:
freeTouch (&myTouch);

или передайте обратно NULL, чтобы вы могли присвоить:

void *freeTouch (Touch *f){
    free (f);
    return NULL;
}
:
myTouch = freeTouch (myTouch);

Вы заметите, что второму не все равнопередаете ли вы значение NULL - вполне допустимо попробовать освободить указатель NULL, поскольку он фактически не выполняет никаких операций (кроме самого вызова функции).

1 голос
/ 02 апреля 2012

Прежде всего, никогда не используйте

x = realloc(x, size);

, потому что, если x выделено раньше и realloc не удается, вы делаете его NULL, пока память еще есть, и поэтому вы создаете мусор.

Во-вторых,

void freeTouch(Touch *f);

получает указатель по значению и поэтому не может изменить сам указатель.Так что ваш f = NULL; не эффективен.Вам нужно изменить свой код на:

int main(){
    Touch *myTouch = NULL, temp;
    int inputCounter = 0;
    //whenever  a touch is recognized:
    ...
    temp = realloc(myTouch,sizeof(*temp) * (inputCounter++));
    if (temp == NULL)
        /* handle error */
    myTouch = temp;
    ...
    // everything works fine until:
    freeTouch(&myTouch);
}

void freeTouch(Touch **f){
    if(f != NULL && *f != NULL){
        free(*f);
        *f = NULL;
    }
}

Sidenote: Это хорошая идея использовать realloc (а также malloc), например:

x = realloc(count * sizeof(*x));

Нетнужно наложить вывод или realloc.Кроме того, sizeof(*x) позволяет вам не повторять тип x каждый раз.

...