调试致命错误-分配:无效块:0000000001F00AEF0:0 0

问题描述 投票:0回答:1

我有一个用R编写的GUI,它使用Tcl / TK包以及一个C.dll,它也使用Tcl库。我对此问题进行了一些研究,它似乎与内存有关。我是一个没有经验的程序员,所以我不确定应该在哪里寻找此内存问题。每个malloc()调用都有一个匹配的free(),并且与类似的Tcl_Alloc()Tcl_Free()相同。这个错误也很难重现,因此恐怕我无法提供可重现的示例,因为它本质上看似随机。然而,一种模式是它似乎仅在程序关闭时发生,尽管这是非常不一致的。

通过发表这篇文章,我希望获得一个逻辑过程,人们应该尝试在Tcl / Tk-C-R应用程序的一般情况下调试此问题。我不是在寻找针对我的代码的解决方案,而是在遇到这个问题时个人应该考虑的问题。

编辑:似乎该错误可能源于C代码的这一点,因此我将在此处发布以发表任何评论:

int ogl_loadDownSampleModel(FILE* file, model_t* model)
{
    char buffer[1000] = { 0 };

    BEG_LING("Surface=");/*set filepointer to tag*/
    PLY_ATTR_GET_INT("Surface=", buffer, &model->dsCount); /*read in dsCount value*/
    printf("Load down sample model: vertex=%d\n", model->dsCount);

    if (model->dsCount <= 0)
    {
        return 0;
    }

    FREE(model->dsVertex);
    model->dsVertex = (float*)malloc(model->dsCount * 3 * sizeof(float));

    /*Read Vertices*/
    for (int i = 0; i < model->dsCount * 3; i += 3)
    {
        fgets(buffer, 300, file);
        sscanf(buffer, "%f %f %f", &model->dsVertex[i], &model->dsVertex[i + 1], &model->dsVertex[i + 2]); /*read in downsampled vertices*/

        if (i >= 3 * 5)
        {
            /*handle outliers and grab coords*/
            if (model->dsVertex[i] < model->dsMin[X]) model->dsMin[X] = model->dsVertex[i];
            if (model->dsVertex[i + Y] < model->dsMin[Y]) model->dsMin[Y] = model->dsVertex[i + Y];
            if (model->dsVertex[i + Z] < model->dsMin[Z]) model->dsMin[Z] = model->dsVertex[i + Z];

            if (model->dsVertex[i] > model->dsMax[X]) model->dsMax[X] = model->dsVertex[i];
            if (model->dsVertex[i + Y] > model->dsMax[Y]) model->dsMax[Y] = model->dsVertex[i + Y];
            if (model->dsVertex[i + Z] > model->dsMax[Z]) model->dsMax[Z] = model->dsVertex[i + Z];
            model->dsVertex[i] = ogl_calCoordinate(model->dsVertex[i], 0, model->delta);// +0.11;
            model->dsVertex[i + 1] = ogl_calCoordinate(model->dsVertex[i + 1], 1, model->delta);
            model->dsVertex[i + 2] = ogl_calCoordinate(model->dsVertex[i + 2], 2, model->delta);
        }
        else
        {
            /*if no outliers, grab coords*/
            model->dsVertex[i] = ogl_calCoordinate(model->dsVertex[i], 0, model->delta);// +0.11;
            model->dsVertex[i + 1] = ogl_calCoordinate(model->dsVertex[i + 1], 1, model->delta);// +1.27;
            model->dsVertex[i + 2] = ogl_calCoordinate(model->dsVertex[i + 2], 2, model->delta);// -0.02;
        }
    }
    double delta[4] = { 0.0 };
    for (int j = 0; j < 3; j++)
    {
        if (model->dsMax[j] - model->dsMin[j] != 0) { // distinct max/min
            delta[j] = (model->dsMax[j] + model->dsMin[j]) / 2; /*midpoint*/
            float tmp = POSITIVE(delta[j]) + model->dsMax[j]; //go beyond delta[j] of max
            if (tmp > delta[3]) //if our jump exceeds maximum threshold
            {
                delta[3] = tmp; //set our new threshold to that jump
            }
        }
        printf("min=%f, max=%f, delta[j]=%f\n", model->dsMin[j], model->dsMax[j], delta[j]);
    }
    for (int i = 15; i < model->dsCount * 3; i += 3)
    {
        //model->dsVertex[i] = calCoordinate(model->dsVertex[i], 0, delta);
        //model->dsVertex[i + 1] = calCoordinate(model->dsVertex[i + 1], 1, delta);
        //model->dsVertex[i + 2] = calCoordinate(model->dsVertex[i + 2], 2, delta);
    }
    return model->dsCount;
}

这里是model_t的结构:

typedef struct model_t
{
    float* vertex;
    float* color;
    float* normal;
    float* dsVertex; //down sample vertex
    int count;
    int dsCount; //the number of down sample vertex
    float max[3];
    float min[3];
    float dsMax[3];
    float dsMin[3];
    float delta[4];
} model_t;
memory tcl tk
1个回答
0
投票

该消息来自Ptr2Block()中的函数tclThreadAlloc.c(或其他一些消息会产生相同的错误消息;可能,但不太可能),这是Tcl的线程专用内存分配器(在Tcl内部广泛使用,以减少全局锁定被击中的次数)。具体来说就是:

if (blockPtr->magicNum1 != MAGIC || blockPtr->magicNum2 != MAGIC) {
    Tcl_Panic("alloc: invalid block: %p: %x %x",
            blockPtr, blockPtr->magicNum1, blockPtr->magicNum2);
}

问题?这些零应为MAGIC(等于0xEF)。这表明something已覆盖内存块的元数据(还应包括该块的大小,但现在可能是热垃圾),并且程序存储完整性不再受信任。 las,此时,我们现在正在处理处于破裂状态的程序,该状态之前发生了破裂。发生恐慌的地方仅是错误的[[检测发生的地方,而不是错误的实际位置

[进一步调试通常是通过构建

everything

的版本并关闭花哨的内存分配器来完成的(在Tcl的代码中,这是通过在构建时定义PURIFY符号来完成的),然后运行结果代码-希望仍然存在错误-使用electricfencepurify之类的工具(因此带有特殊符号名称)来查看发现了哪些类型的越界错误;他们非常擅长解决此类问题。
© www.soinside.com 2019 - 2024. All rights reserved.