2017-04-12 58 views
1

它分析變量的生命週期,並簡單地插入在正確的地方清理函數調用?它是否有任何間接費用?如何GNU C擴展__attribute __(__ cleanup__)工作?

我寫的簡單的兩段代碼比較性能,並沒有優化編譯它們。

代碼1:

#include <stdio.h> 
#include <stdlib.h> 

void clean_up(int **final_value) 
{ 
    free(*final_value); 
} 

int main(int argc, char **argv) 
{ 
    for (int i = 0; i < 10000000; i++) { 
    int *avar = malloc(sizeof(int)); 
    clean_up(&avar); 
    } 

    return 0; 
} 

碼2:

#include <stdio.h> 
#include <stdlib.h> 

void clean_up(int **final_value) 
{ 
    free(*final_value); 
} 

int main(int argc, char **argv) 
{ 
    for (int i = 0; i < 10000000; i++) { 
    int *avar __attribute__ ((__cleanup__(clean_up))) = malloc(sizeof(int)); 
    } 

    return 0; 
} 

而且他們的表現都相當類似。當變量超出範圍

+0

在這兩種情況下的性能將是相同的。在第一種情況下,clean_up func由main調用。在第二種情況下,__cleanup__屬性將在main結束時調用clean_up函數。 – Rajeshkumar

+2

[不要將'malloc'的結果放在C中](http://stackoverflow.com/q/605845/995714) –

+0

@Rajeshkumar:清理髮生在包含塊的末尾,而不是'main'的末尾。 –

回答

3

你會更好地與一些優化編譯,特別是如果你想看看生成的彙編程序代碼(與gcc -S -fverbose-asm -O編譯)

直覺behind__attribute__((cleanup))是GCC實際上是在爲所有的C編譯器,C++,Ada,Fortran,Go ....該屬性強制使用與局部變量的C++析構函數相同的內部表示。清理髮生在當前塊範圍的末尾(例如,在塊的右大括號}處)。所以編譯器正在將你的代碼2清理成相當於code1的代碼。

對全局或靜態變量的析構函數的事情(這是main後運行已恢復)是__attribute__((destructor))上的功能(這也是在dlclose時間插件運行)。

因此,要了解這些屬性,你會更好地認爲C++條款。

我的意見是,如果你需要這些cleanup屬性,你應該用C++而不是C編碼你的東西。你的代碼會更可讀,更少依賴於編譯器。我覺得cleanup實際上只在生成的C代碼中有用。我從來沒有使用它(並且感覺當我需要它時,我應該切換到C++)。

1

的清理函數被調用。它並不在乎,這是否會讓其他指針懸而未決。