关于 malloc()ed 数组数组的命运

发布于 2024-09-12 06:51:53 字数 4276 浏览 12 评论 0原文

我在 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 吗?无论如何,我打算这样做,通过出现段错误来发现任何错误,但还没有时间合并它。 3. 我对 malloc() 类变量是否正确?有更好的方法来实现这一目标吗?否则我没有其他已知的方式将此信息提供给渲染器。

my first question on Stackoverflow.

Let me start with a bit of code. It's a bit repetitive so I'm going to cut out the parts I repeat for different arrays (feel free to ask for the others). However, please ignore the code in preference to answering the Qs at the bottom. Firstly: thank you to answerers in advance. Secondly: the freeing of data.

@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);
    }
}

(I will get to the calling of this in a moment). Now for where I malloc() the arrays.

- (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];
}

Finally, the bit which calls everything (this is a separate class.)

- (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;
}

What I'm doing here is loading a molecule from a PDB file into memory and displaying it on an OpenGL view window. The second time I load a molecule (which will run loadPDB: above) I get the Giant Triangle Syndrome and Related Effects... I will see large triangles over my molecule.

However, I am releasing and reallocating my PDBHelper and ES1Renderer every time I load a new molecule. Hence I was wondering:

1. whether the helixVertices, helixIndices and helixColors which I have declared as class-wide variables are actually re-used in this instance. Do they point to the same objects?

2. Should I be setting all my variables to NULL after freeing? I plan to do this anyway, to pick up any bugs by getting a segfault, but haven't got round to incorporating it.
3. Am I even right to malloc() a class variable? Is there a better way of achieving this? I have no other known way of giving this information to the renderer otherwise.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

寄风 2024-09-19 06:51:53

我无法回答你的一般性问题。里面东西太多了。然而,这引起了我的注意:

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

我认为这东西可能会泄漏。无论如何,这没有意义。

如果 renderer.helper 是保留或复制属性,请勿释放它。它已经具有在分配新值时释放旧值的代码。也不要保留分配给它的对象。

您已经分配了一个Helper,因此无需再次保留它。上面的代码应该重写为:

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

另外,我认为你的螺旋分配数组可能应该是实例变量。就目前情况而言,如果您有多个 ES1Renderer,它们就会共享这些变量。

I can't answer your general questions. There's too much stuff in there. However, this caught my eye:

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

I think this stuff possibly leaks. It doesn't make sense anyway.

If renderer.helper is a retain or copy property, do not release it. It already has code that releases old values when it is assigned new values. Also do not retain objects you assign to it.

You have alloc'd aHelper, so there's no need to retain it again. The above code should be rewritten something like:

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

Also, I think your helix malloced arrays should probably be instance variables. As things stand, if you have more than one ES1Renderer, they are sharing those variables.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文