2017-04-12 16 views
1

変数のライフサイクルを分析し、クリーンアップ関数呼び出しを適切な場所に挿入するだけですか?それには間接費がかかりますか?GNU Cの拡張機能__attribute __(__ cleanup__)はどのように機能しますか?

パフォーマンスを比較するための2つの簡単なコードを作成し、最適化なしでコンパイルしました。

CODE1:

#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によって呼び出されます。 2番目のケースでは、__cleanup__属性は、メインが終了したときにclean_up関数を呼び出します。 – Rajeshkumar

+2

[Cで 'malloc'の結果をキャストしないでください](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++の言葉をよく考えてください。

私の意見では、これらの属性が必要な場合は、CではなくC++でコードする必要があります。コードははるかに読みやすく、コンパイラに依存しません。私はcleanupが実際には生成されたCコードでのみ役に立つと感じています。私はそれを使用したことがありませんでした(そして、私がそれを必要とするとき、私はC++に切り替える必要があると感じます)。

1

変数が有効範​​囲外になると、クリーンアップ関数が呼び出されます。これが他のポインタをぶら下げてしまうかどうかは気にしません。あなたが生成されたアセンブラコードに見たい場合は、より良い、特に、いくつかの最適化をコンパイルします

関連する問題