此代码模仿了一些带有malloced内存的图像处理,它是问题的一个提炼示例。如果在其他级别(包括"最快最小的")进行优化,它可以正常运行,但在GCC_OPTIMIZATION_LEVEL = 3 AKA最快[-03]和最快进取时失败。它仅在设备上崩溃,见于6,5s,5和各种IOS 9.3,8.4。
有关分配大小的问题会加剧问题。代码中有一些注释可以帮助它失败。
通过创建单个视图应用项目进行重现,将优化级别设置为"最快"并将此代码粘贴到main中并从自动释放池中调用它,或者将其粘贴到视图控制器中并从viewDidLoad或任何您喜欢的地方调用它。
调试器在启用优化时非常有用,但崩溃发生在" * writeIter = readIter-> d;" EXC_BAD_ACCESS代码= 1
这样告诉我它的读取和触发EXC_BAD_ACCESS的地址与readEnd相同。这应该永远不会发生,因为那时候应该阻止......优化者错误或愚蠢的错误?
#import <stdlib.h>
#import <stdio.h>
/**
Requires this to fail -> GCC_OPTIMIZATION_LEVEL = 3
This won't do it -> GCC_OPTIMIZATION_LEVEL = s
*/
typedef struct {
unsigned char a, b, c, d;
} foo;
void boom()
{
char* memory[1000];
// these sizes are important to reproducing this issue, changing them by +-1 will make it go away
int height = 960; //480,960,1920
int width = 1280; //640,1280,2560
int depth = sizeof(foo);
printf("height = %d, width = %d, total = %d\n\n", height, width, height*width*depth);
for (int i = 0; i < 1000; ++i)
{
memory[i] = malloc(20000); // allocate memory to force the allocations of readBuf and writeBuf to move, numbers
// less than 15k don't effect the alloced addresses of the bufs, so we keep getting
// the same ones and no boom.
foo* readBuf = malloc(height*width*depth);
unsigned char* writeBuf = malloc(height*width); // smaller than read
foo *readIter = readBuf;
foo *readEnd = readBuf + height*width; // only read size of smaller
unsigned char* writeIter = writeBuf;
printf("test: i = %d, readIter = %p, readEnd = %p, writeIter = %p\n", i, readIter, readEnd, writeIter);
while (readIter < readEnd)
{
*writeIter = readIter->d; // you died here during a read, and readIter == readEnd, look at the EXC_BAD_ACCESS address
// (printfed) it's readEnd, and that isn't supposed to happen with the conditional.
++writeIter;
++readIter;
}
free(readBuf);
free(writeBuf);
}
for (int i = 0; i < 1000; ++i)
{
free(memory[i]);
}
}