Невозможно освободить указатель на ранее выделенную структуру - PullRequest
2 голосов
/ 05 апреля 2011

Я создаю легкую систему частиц. У меня есть две структуры typedef. Первый представляет одну частицу с некоторыми полями. Второй представляет собой систему частиц. Моя проблема в том, что я не могу освободить память, выделенную для каждой частицы. На самом деле не знаю, что не так. Вот структуры:

typedef struct {
   float m;  
   float *x;  
   float *v;    
   float *f;     
   float R;
} *Particle;

typedef struct {
   Particle *p;
   int n; 
   float t; 
} *ParticleSystem;

и вот код для выделения

ParticleSystem sys = (ParticleSystem) malloc(sizeof(ParticleSystem));  
sys->p =  (Particle *) malloc(sizeof(Particle)*noOfParticles);

for(int i=0;i<noOfParticles;i++){
    sys->p[i] = (Particle)malloc(sizeof(Particle));

    sys->p[i]->f = (float*)malloc(sizeof(float)*2);
    sys->p[i]->f[0] = 0.0f;
    sys->p[i]->f[1] = 0.0f;

    ...

    sys->p[i]->R = radius;
    sys->p[i]->m = mass;

}

sys->n=noOfParticles;
sys->t = 0.0f;

и освобождают

int n = sys->n;
for(int i=0;i<n;i++){
    free(sys->p[i]->f);

    ...

    free(sys->p[i]);//here it breaks
}
free(sys->p);
free(sys);

В строке "free (sys-> p [i]) он разрывается. Я не знаю почему, потому что сначала я делаю это
sys-> p [i] = (Particle) malloc (sizeof (Particle)) для выделения. Visual Studio сообщает: «HEAP [template.exe]: неверный адрес, указанный для RtlValidateHeap (01E70000, 01E749B0) Windows запустила точку останова в файле template.exe. "

Ответы [ 6 ]

5 голосов
/ 05 апреля 2011

Я давно занимался программированием на C / C ++, но разве эти typedef не объявляют Particle типа указатель на эту структуру и ParticleSystem типа указатель на- что-другой-структура? Если это так, когда вы выделяете память, вы выделяете достаточно памяти только для хранения указателя , а не фактической структуры.

Например:

#include <iostream>

using namespace std;

typedef struct {
  float m;
  float *x;
  float *v;
  float *f;
  float R;
} *Particle;

typedef struct {
  Particle *p;
  int n;
  float t;
} *ParticleSystem;

int main()
{
  cout << "sizeof(Particle) = " << sizeof(Particle) << endl;
  cout << "sizeof(ParticleSystem) = " << sizeof(ParticleSystem) << endl;
  return 0;
}

и когда я запускаю эту программу, я получаю:

sizeof(Particle) = 4
sizeof(ParticleSystem) = 4
4 голосов
/ 05 апреля 2011

Если это C, вы действительно не должны приводить к типу возвращаемое значение malloc().Если это C ++, вам действительно не следует использовать malloc().

Кроме того, я бы предложил не typedef: убирая ваши указатели, это усложняет отслеживание кода и обнаружение ошибок.

Кроме того, нет смысла использовать malloc(), если вы знаете, что массив всегда будет иметь постоянный маленький размер, например два (Particle.f используется таким образом).Просто объявите массив напрямую и сохраните malloc() s и связанную с этим путаницу.

4 голосов
/ 05 апреля 2011

Я бы не использовал звездочку при создании такой typedef. Это легко приводит к путанице при использовании памяти и использовании указателей. Просто используйте

typedef struct {
   float m;  
   float *x;  
   float *v;    
   float *f;     
   float R;
} Particle;

Это сделает это намного более понятным, я даже не знаю, какое поведение вызывает ваш typedef (вы, вероятно, выделяете место только для указателя)

Просто возьмите строку в этих двух строках:

sys->p =  (Particle *) malloc(sizeof(Particle)*noOfParticles);
sys->p[i] = (Particle)malloc(sizeof(Particle));

Я предполагаю, что вы хотите получить память для указателей в первую очередь и память для самой структуры во втором. Но как это должно работать? Вы используете sizeof (Particle) в обоих mallocs.

1 голос
/ 05 апреля 2011

Я бы начал с фиксации объявления структуры:

} Particle;

и

} ParticleSystem;

вместо указателей.

А затем обновите оставшуюся часть кода, чтобы отразить эти изменения, начиная с:

ParticleSystem* sys = (ParticleSystem*) malloc(sizeof(ParticleSystem));  
sys->p =  (Particle*) malloc(sizeof(Particle) * noOfParticles);
1 голос
/ 05 апреля 2011

Попробуйте изменить:

typedef struct {
float m;  
float *x;  
float *v;    
float *f;     
float R;
} *Particle;

на

typedef struct {
float m;  
float *x;  
float *v;    
float *f;     
float R;
} Particle;

Вам нужно иметь Particle, чтобы иметь *Particle и чтобы sizeof(Particle) работало... То же самое касается ParticleSystem

0 голосов
/ 05 апреля 2011

Во-первых, у вас есть Particle *p, который вы можете выделить как отдельную частицу или массив частиц.

Вы выделяете * p как массив во второй строке, поэтому вы НЕ должны выделять ихснова внутри цикла for, ЕСЛИ вы не используете Particle **p, а затем выделяете * (p) в качестве массива указателей на Particle, затем вы размещаете каждую частицу внутри цикла for.Я не рекомендую.

Как упоминалось выше, удалить объявление указателя из структур.

И, после этого, вам не нужно перераспределять каждую частицу (так как p являетсяобычный указатель), вы должны освободить его только с free(sys->p);, потому что вы выделяете каждую отдельную частицу как прямое место в памяти, а не как указатели, как я уже сказал.

Надеюсь, это поможет:)

...