似乎无法调试优化代码。我花了太长时间试图超越编译器。由于编译器优化了我的代码,我很难做一个简单的检查,如果我的结构是否为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;
有没有办法防止拉格被优化?
答案 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 - 编译器根本不打算写它,因为代码在没有它的情况下具有相同的效果。
调试优化代码可能很困难。您可以在没有优化的情况下进行编译,并尝试重现问题,或在调试优化代码时检查调试器中的机器代码和寄存器。