О судьбе malloc () ed массивов массивов - PullRequest
1 голос
/ 29 июля 2010

мой первый вопрос по Stackoverflow.

Позвольте мне начать с небольшого кода.Это немного повторяется, поэтому я собираюсь вырезать части, которые я повторяю для разных массивов (не стесняйтесь спрашивать другие).Однако, пожалуйста, не обращайте внимания на код, а не отвечайте на вопросы внизу.Во-первых: заранее благодарю ответчиков.Во-вторых: освобождение данных.

@implementation ES1Renderer

GLfloat **helixVertices;
GLushort **helixIndices;
GLubyte **helixColors;

- (void)freeEverything
{
    if (helixVertices != NULL)
    {
        for (int i=0; i < alphasToFree / 30 + 1; i++)
            free(helixVertices[i]);
        free(helixVertices);
    }

    if (helixIndices != NULL)
    {
        for (int i=0; i < alphasToFree / 30 + 1; i++)
            free(helixIndices[i]);
        free(helixIndices);
    }

    if (helixColors != NULL)
    {
        for (int i=0; i < alphasToFree / 30 + 1; i++)
            free(helixColors[i]);
        free(helixColors);
    }
}

(я скоро докажу это).Теперь, где я malloc () массивов.

- (void)askForVertexInformation
{
    int nrows = self.helper.numberOfAtoms / 300;
    int mrows = [self.helper.bonds count] / 300;

    int alphaCarbonRows = [self.helper.alphaCarbons count] / 30;

    helixVertices = malloc(alphaCarbonRows * sizeof(GLfloat *) + 1);
    helixIndices = malloc(alphaCarbonRows * sizeof(GLfloat *) + 1);
    helixColors = malloc(alphaCarbonRows * sizeof(GLfloat *) + 1);

    for (int i=0; i < alphaCarbonRows + 1; i++)
    {
        helixVertices[i] = malloc(sizeof(helixVertices) * HELIX_VERTEX_COUNT * 3 * 33);
        helixIndices[i] = malloc(sizeof(helixIndices) * HELIX_INDEX_COUNT * 2 * 3 * 33);
        helixColors[i] = malloc(sizeof(helixColors) * HELIX_VERTEX_COUNT * 4 * 33);

    }
    [self.helper recolourVerticesInAtomRange:NSMakeRange(0, [self.helper.alphaCarbons count]) withColouringType:CMolColouringTypeCartoonBlue forMasterColorArray:helixColors forNumberOfVertices:HELIX_VERTEX_COUNT difference:30]; 

    self.atomsToFree = self.helper.numberOfAtoms;
    self.bondsToFree = [self.helper.bonds count];
    self.alphasToFree = [self.helper.alphaCarbons count];
}

Наконец, бит, который вызывает все (это отдельный класс.)

- (void)loadPDB:(NSString *)pdbToLoad
{
    if (!self.loading)
    {
        [self performSelectorOnMainThread:@selector(stopAnimation) withObject:nil waitUntilDone:YES];
        [self.renderer freeEverything];
        [renderer release];
        ES1Renderer *newRenderer = [[ES1Renderer alloc] init];
        renderer = [newRenderer retain];
        [self performSelectorOnMainThread:@selector(stopAnimation) withObject:nil waitUntilDone:YES]; // need to stop the new renderer animating too!
        [self.renderer setDelegate:self];
        [self.renderer setupCamera];
        self.renderer.pdb = nil;
        [renderer resizeFromLayer:(CAEAGLLayer*)self.layer];
        [newRenderer release];

        NSInvocationOperation *invocationOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(setup:) object:pdbToLoad];
        [self.queue addOperation:invocationOperation];
        [invocationOperation release];
    }
}

- (void)setup:(NSString *)pdbToLoad
{
    self.loading = YES;

    [helper release];
    [renderer.helper release];
    PDBHelper *aHelper = [[PDBHelper alloc] initWithContentsOfFile:pdbToLoad];
    helper = [aHelper retain];
    renderer.helper = [aHelper retain];
    [aHelper release];

    if (!resized)
    {
        [self.helper resizeVertices:11];
        resized = YES;
    }

    self.renderer.helper = self.helper;

    [self.helper setUpAtoms];
    [self.helper setUpBonds];

    if (self.helper.numberOfAtoms > 0)
        [self.renderer askForVertexInformation];
    else
    {           
        // LOG ME PLEASE.
    }

    [self performSelectorOnMainThread:@selector(removeProgressBar) withObject:nil waitUntilDone:YES];
    [self performSelectorOnMainThread:@selector(startAnimation) withObject:nil waitUntilDone:YES];
    self.renderer.pdb = pdbToLoad;

    self.loading = NO;
}

То, что я делаю здесь, этозагрузка молекулы из файла PDB в память и отображение ее в окне просмотра OpenGL.Во второй раз, когда я загружаю молекулу (которая будет работать на loadPDB: выше), я получаю синдром гигантского треугольника и связанные с ним эффекты ... Я буду видеть большие треугольники над моей молекулой.

Однако я освобождаю и перераспределяюмой PDBHelper и ES1Renderer каждый раз, когда я загружаю новую молекулу.Поэтому мне было интересно:

1. действительно ли в этом случае повторно используются helixVertices, helixIndices и helixColors, которые я объявил как общеклассовые переменные.Они указывают на одни и те же объекты?
2. Должен ли я устанавливать все мои переменные в NULL после освобождения?В любом случае я планирую сделать это, чтобы выявить любые ошибки, получив segfault, но пока не дошел до их включения.3. Прав ли я даже на malloc () переменную класса?Есть ли лучший способ добиться этого?У меня нет другого известного способа передать эту информацию визуализатору в противном случае.

1 Ответ

1 голос
/ 29 июля 2010

Я не могу ответить на ваши общие вопросы.Там слишком много вещей.Однако, это привлекло мое внимание:

[helper release];
[renderer.helper release];
PDBHelper *aHelper = [[PDBHelper alloc] initWithContentsOfFile:pdbToLoad];
helper = [aHelper retain];
renderer.helper = [aHelper retain];
[aHelper release];

Я думаю, что этот материал, возможно, протекает.В любом случае это не имеет смысла.

Если renderer.helper является свойством сохранения или копирования, не выпускайте его.У него уже есть код, который освобождает старые значения, когда ему назначаются новые значения.Также не сохраняйте объекты, которые вы ему назначаете.

У вас есть alloc'd aHelper, поэтому нет необходимости сохранять его снова.Приведенный выше код должен быть переписан примерно так:

[helper release];
helper = [[PDBHelper alloc] initWithContentsOfFile:pdbToLoad];
renderer.helper = helper;

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

...