简体   繁体   English

重新分配引起的Malloc错误

[英]Malloc Error Caused by Realloc

I've been scratching my head over this for hours. 我已经为此努力了好几个小时。 I'm running Mac OS X 10.8, with XCode 5. I've been getting the following error: 我正在运行带有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

Unfortunately, object 0x1006487b8 is freed at this point, and my debugger has no recollection of what was there. 不幸的是,此时object 0x1006487b8已被释放,并且我的调试器无法回忆那里的内容。

The problem is, the error never occurs in the same place. 问题是,该错误永远不会在同一位置发生。 I can only assume that a bit of memory isn't freed properly, and then the computer tries to use it for some other purpose and winds up confused. 我只能假设一点内存没有被正确释放,然后计算机尝试将其用于其他目的并最终造成混乱。

My code is using SDL 2, and as far as I can tell, the only free -like function call occurs in the following form with a realloc : 我的代码使用的是SDL 2,据我所知,唯一类似于free的函数调用以以下形式发生,并带有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 is a static, file-scope pointer to an array of gates and is declared as such at the top of the file: gates是指向gates数组的静态文件范围指针,并在文件顶部声明为:

static LGC_Gate* gates = NULL;
numgates is initialized to zero at the beginning of the file, and represents the number of gates currently in use. numgates在文件开头被初始化为零,并表示当前正在使用的门数。 gates should always be of size numgates * sizeof(LGC_Gate) . gates的大小应始终为numgates * sizeof(LGC_Gate)

My plan was to hold all gates created by the user in a single array, so that it was easy to tally them and get each at a moment's notice. 我的计划是将用户创建的所有门都保存在一个阵列中,这样可以很容易地对它们进行汇总,并立即得到通知。 The LGC_CreateEmptyGate function is used like this, for example: 像这样使用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;

}

Have I done something horribly wrong? 我做错了什么吗?

Update 更新

I have done some debugging with the following code: 我已经使用以下代码进行了一些调试:

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.          
        }
    }
}

To my complete surprise, this actually outputs an error, and indeed crashes on some of the pointers. 令我完全惊讶的是,这实际上输出了一个错误,并且确实在某些指针上崩溃了。 CORRECTION: The erroring pointer always seems to be the third one. 更正:错误的指针始终似乎是第三个指针。 Note that LGC_InitActGate calls LGC_InitEmptyGate once, and simply copies data for the rest of its duration. 请注意, LGC_InitActGate调用一次LGC_InitEmptyGate ,并在剩余LGC_InitEmptyGate简单地复制数据。 What is going on? 到底是怎么回事?

Update 2 更新2

Well, I believe I've discovered the error now. 好吧,我相信我现在已经发现了错误。 Every time realloc is called, the entire block of memory may or may not relocate, which renders the array of 5 pointers I had useless and pointing to old, freed memory. 每次调用realloc时,整个内存块可能会或可能不会重定位,这使我拥有的5个指针数组无效,并指向旧的,已释放的内存。 This makes total sense, but it's one heckuva bug. 完全有道理,但这只是一个heckuva错误。 I should've noticed before. 我之前应该注意到。 I'm not sure how to fix this, but thanks for the help I got. 我不确定如何解决此问题,但感谢您的帮助。

What this error is telling you is that the system is about to try and allocate some memory, but when it went to it's free pool, the next available block appears to have been corrupted. 该错误告诉您,系统将尝试分配一些内存,但是当它进入其空闲池时,下一个可用块似乎已损坏。

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.

It is usually the case that the location of the crash is merely the detection and not the cause. 通常情况下,碰撞的位置只是检测而已,而不是原因。

One way you can sometimes track down a crash like this is look at the data at the address (and get lucky and have something recognizable like a string or well known values). 有时您可以像这样查找崩溃的一种方法是查看地址上的数据(很幸运,并且可以识别字符串或众所周知的值)。

Otherwise, it's time to break out valgrind. 否则,是时候打破valgrind了。

每次从main调用realloc ,内存块可能会或可能不会重定位,这会使数组TestGates拥有指向无效内存的元素。

The code looks fine to me, although it could be simplified since you don't actually need to special-case the starting condition. 该代码对我来说看起来不错,尽管可以简化代码,因为您实际上不需要特殊化启动条件。 [Note 1] [注1]

Are you certain that you're not holding on to a pointer to a "gate" somewhere in the code? 您确定您没有坚持使用代码中某个“门”的指针吗? You have to be really careful with auto-reallocating vectors, particularly global ones which might be modified in a function: 您必须非常小心自动重新分配向量,尤其是可能在函数中修改的全局向量:

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

Note 1: From the Posix realloc specification : 注1:根据Posix realloc规范

If ptr is a null pointer, realloc() shall be equivalent to malloc() for the specified size. 如果ptr是一个空指针,则对于指定的大小,realloc()将等效于malloc()。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM