1


0

配列のmalloc()ed配列の運命について

Stackoverflowに関する私の最初の質問。

少しのコードから始めましょう。 それは少し反復的ですので、異なる配列のために繰り返す部分を切り取ります(他の配列についてはお気軽にお尋ねください)。 ただし、下部のQに回答するよりも優先してコードを無視してください。 まず、事前に回答者に感謝します。 第二に:データの解放。

@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ビューウィンドウに表示することです。 2回目に分子を読み込むと(上記の `loadPDB:`が実行されます)、Giant Triangle Syndrome and Related Effectsが表示されます…​ 分子の上に大きな三角形が表示されます。

ただし、新しい分子をロードするたびにPDBHelperとES1Rendererを解放して再割り当てしています。 したがって、私は疑問に思っていました:

{空} 1 クラス全体の変数として宣言したhelixVertices、helixIndices、helixColorsがこのインスタンスで実際に再利用されるかどうか。 それらは同じオブジェクトを指しますか? + 2. 解放後にすべての変数をNULLに設定する必要がありますか? とにかく、セグメンテーション違反を取得してバグを拾うためにこれを行う予定ですが、それを組み込むことはできません。 3. クラス変数をmalloc()する権利さえありますか? これを達成するためのより良い方法はありますか? そうでなければ、この情報をレンダラーに提供する他の既知の方法はありません。

1 Answer


1


一般的な質問には答えられません。 そこにはあまりにも多くのものがあります。 しかし、これは私の目を引きました:

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

このようなものはおそらく漏れていると思います。 とにかく意味がありません。

renderer.helperがretainまたはcopyプロパティである場合、リリースしないでください。 新しい値が割り当てられたときに古い値を解放するコードが既にあります。 また、割り当てたオブジェクトを保持しないでください。

aHelperを割り当てたので、再度保持する必要はありません。 上記のコードは次のように書き換える必要があります。

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

'' '' '

また、ヘリックスのmallocされた配列はおそらくインスタンス変数であるべきだと思います。 現状では、複数のES1Rendererがある場合、それらはそれらの変数を共有しています。