Xcode Optimizer Bug还是愚蠢的错误?

时间:2016-06-10 19:13:06

标签: ios malloc code-generation compiler-optimization xcode7.3

此代码模仿了一些带有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]);
    }
}

0 个答案:

没有答案