结构指针使用-O3选项进行优化

时间:2015-07-08 23:37:48

标签: c optimization struct

似乎无法调试优化代码。我花了太长时间试图超越编译器。由于编译器优化了我的代码,我很难做一个简单的检查,如果我的结构是否为null,请不要误解我的确想保留-O3选项,如果可能的话加速我的代码,但是如果由于编译器的优化,我不断收到很多错误,我可能会把它关掉。

我有一个线程,它会尝试从数组中将结构条目出列并将它们放入数据库中,但由于某种原因结构已经过优化。

void *queue_func(void *param){
    LogArgs* largs;
    pthread_mutex_t *mx = (pthread_mutex_t*) param;

    InitQueue();
    while(!needQuit(mx)){
        if((largs = Dequeue()) != NULL){ // the boolean result is true here
            interrupt_log(largs->event, largs->rawtime); // yet largs is NULL here!!!
        }
        usleep(50000);
    }
    return NULL;
}

这里的参考是Dequeue函数和struct:

LogArgs* Dequeue(){
    LogArgs* largs;

    if(isEmpty()) return NULL;
    else{
        largs = &queue[++head % MAX_SIZE];
        return largs;
    }
}

这是结构:

typedef struct {
    time_t *rawtime;
    char event[129];
} LogArgs;

有没有办法防止拉格被优化?

2 个答案:

答案 0 :(得分:5)

完全优化调试 - 正如您已经注意到的那样 - 只是一种痛苦。使用volatile等进行欺骗并没有多大帮助,完全禁用优化可能会更快,因为volatile禁止编译器将变量放入寄存器(例如)。

尝试-Og(因为gcc 4.8)。这应该能够实现不干扰调试的优化。

如果你有两个线程之间的数据结构,你告诉编译器它们是特殊的。但是,对于具有缓存等的现代多CPU系统,volatile几乎没有用于应用程序层代码。使用原子类型(stdatomic.h) - 完全支持自gcc 4.9以来。这些包括障碍(aka围栏),以保证访问的正确排序。

答案 1 :(得分:1)

如果Dequeue()函数位于同一个翻译单元(粗略地讲,同一个.c文件),那么它很可能被内联到queue_func()中,所以代码queue_func()最终看起来更像是这样:

void *queue_func(void *param)
{
    LogArgs* largs;
    pthread_mutex_t *mx = (pthread_mutex_t*) param;

    InitQueue();
    while (!needQuit(mx))
    {
        if (!isEmpty()) // the boolean result is true here
        {
            largs = &queue[++head % MAX_SIZE];
            interrupt_log(largs->event, largs->rawtime); // yet largs is NULL here!!!
        }
        usleep(50000);
    }
    return NULL;
}

...然后编译器发现设置largs毫无意义,因为它可以将其转换为:

void *queue_func(void *param)
{
    LogArgs* largs;
    pthread_mutex_t *mx = (pthread_mutex_t*) param;

    InitQueue();
    while (!needQuit(mx))
    {
        if (!isEmpty()) // the boolean result is true here
        {
            size_t temp_index = ++head % MAX_SIZE;
            interrupt_log(queue[temp_index].event, queue[temp_index].rawtime); // yet largs is NULL here!!!
        }
        usleep(50000);
    }
    return NULL;
}

...现在很明显为什么largs可以为NULL - 编译器根本不打算写它,因为代码在没有它的情况下具有相同的效果。

调试优化代码可能很困难。您可以在没有优化的情况下进行编译,并尝试重现问题,或在调试优化代码时检查调试器中的机器代码和寄存器。