1

几个小时以来,我一直在为此挠头。我正在运行带有 XCode 5 的 Mac OS X 10.8。我收到以下错误:

malloc: *** error for object 0x1006487b8: incorrect checksum for freed object - object was            
probably modified after being freed.
*** set a breakpoint in malloc_error_break to debug

不幸的是,object 0x1006487b8此时已释放,我的调试器不记得那里有什么。

问题是,错误永远不会发生在同一个地方。我只能假设没有正确释放一些内存,然后计算机尝试将其用于其他目的并最终感到困惑。

我的代码使用的是 SDL 2,据我所知,唯一free的 -like 函数调用以以下形式出现realloc

static LGC_Gate* LGC_CreateEmptyGate(){
    if (!gates) {
        gates = malloc(sizeof(LGC_Gate));
        if (!gates)
            return NULL;
    }
    else{
        LGC_Gate* tmpgates = realloc(gates, sizeof(LGC_Gate) * (numgates + 1));
        if (tmpgates)
            gates = tmpgates;
        else
            return NULL;
    }
    numgates++;
    gates[numgates - 1].id = numgates - 1;
    return &(gates[numgates - 1]);
}

gates是指向门数组的静态文件范围指针,并在文件顶部声明为:

static LGC_Gate* gates = NULL;
numgates在文件开头初始化为零,表示当前使用的门数。gates应该总是 size numgates * sizeof(LGC_Gate)

我的计划是将用户创建的所有门保存在一个数组中,以便轻松统计它们并立即获得每个门。该LGC_CreateEmptyGate函数是这样使用的,例如:

LGC_Gate* LGC_InitActGate(LGC_Action act, uint8_t innum, uint8_t outnum){
    LGC_Gate* product = LGC_CreateEmptyGate();
    if (!product)
        return NULL;

    product->rule.type = LGC_FUNCTION;
    product->rule.act = act;

    product->input.used = innum;
    product->input.val = 0;
    product->output.used = outnum;
    product->output.val = 0;

    int i;
    for (i = 0; i < 8; i++) {
        product->inputfrom[i].active = 0;
    }

    return product;

}

我做错了什么可怕的事情吗?

更新

我已经使用以下代码进行了一些调试:

printf("%d\n", sizeof(LGC_Gate));
LGC_Gate* TestGates[5];
//Go through the gates, initialize each of them, record the value of their ptr,
//and if any are LESS than sizeof(LGC_Gate) apart, report an error.
int gcount;
for (gcount = 0; gcount < 5; gcount++) {
    TestGates[gcount] = LGC_InitActGate(LGC_NOR, 2, 1);
    printf("%p\n", TestGates[gcount]);
    if (gcount < 4) {
        if (TestGates[gcount] + sizeof(LGC_Gate) > TestGates[gcount + 1]) {
            printf("Error!");
            //TestGates[gcount + 1]->id = 4;  If this line were uncommented, 
            //                                BAD_ACCESS ensues.          
        }
    }
}

令我完全惊讶的是,这实际上输出了一个错误,并且确实在某些指针上崩溃了。更正:错误指针似乎总是第三个。请注意,LGC_InitActGate调用LGC_InitEmptyGate一次,并在其剩余时间内简单地复制数据。到底是怎么回事?

更新 2

好吧,我相信我现在已经发现了错误。每次调用 realloc 时,整个内存块可能会或可能不会重新定位,这使得我拥有的 5 个指针数组无用并指向旧的、已释放的内存。这是完全有道理的,但这是一个巨大的错误。我以前应该注意到的。我不知道如何解决这个问题,但感谢我得到的帮助。

4

3 回答 3

1

每次realloc调用 frommain时,内存块可能会或可能不会重新定位,这会使数组TestGates中的元素指向无效内存。

于 2013-10-24T13:33:09.617 回答
1

这个错误告诉你的是系统即将尝试分配一些内存,但是当它进入它的空闲池时,下一个可用块似乎已损坏。

void* p = malloc(100);
free(p);
strcpy(p, "How do you like these apples, malloc?";
p = malloc(100); // <-- crash may happen here, depending on how the free list works.

通常情况下,碰撞的位置仅仅是检测而不是原因。

有时可以追踪这样的崩溃的一种方法是查看地址处的数据(幸运的是,有一些可识别的东西,如字符串或众所周知的值)。

否则,是时候打破 valgrind 了。

于 2013-10-24T04:50:24.980 回答
0

该代码对我来说看起来不错,尽管它可以被简化,因为您实际上并不需要对起始条件进行特殊处理。[注1]

您确定您没有在代码中的某处保留指向“门”的指针吗?您必须非常小心自动重新分配向量,特别是可能在函数中修改的全局向量:

LGC_Gate* product = LGC_CreateEmptyGate();
some_innocuous_looking_function();  // Oops, this function calls CreateEmptyGate
product->output.val = some_value;

注 1:来自 Posix realloc 规范

如果 ptr 是空指针,realloc() 应等效于指定大小的 malloc()。

于 2013-10-24T03:28:38.227 回答