リリースとデバッグのコンパイル済みプログラムのソースコードに違いはありますか?
ソースコードと、ライブラリまたはプログラムをコンパイルするためのオプションによって異なります。以下は私が知っているいくつかの違いです。
"デバッグおよび診断" の最も単純なassert
ある
をアサートします。これらは、NDEBUG
がでないときに有効です。が定義されています。アサーションは自己デバッグコードを作成し、予期しない条件に遭遇したときにスナップします。トリックはすべてを主張しなければならないということです。パラメータと状態を検証するたびに、アサートが表示されます。どこでもアサーションがある場合は、if
を参照して、パラメータと状態を検証してください。
アサートのないコードベースが表示されたら笑います。私は自分自身に言いますが、開発者はデバッガの下でそれを無駄にしていると手に余りにも多くの時間を持っています。私はしばしばあなたが主張を使わない理由を尋ねます。彼らは通常次のように答えます。
Posix assert
は電話をしていますのでabort
を呼び出します。プログラムをデバッグしている場合は、通常、コードをステップ実行して、assert
の原因となった負の条件をコードがどのように処理するかを確認します。プログラムの終了は "デバッグと診断"の目的で失敗します。それは、C/C++の歴史の中で最悪の決定でなければなりません。誰もが中止の理由を思い出してはいないようです(数年前、私はさまざまなC/C++標準リストの系図を追跡しようとしました)。
通常、無効なPosixアサーションは、assert
のように、LinuxではSIGTRAP
、WindowsではDebugBreak
が呼び出されます。例えば、のサンプルを参照してください。 Posix assert
をあなたのアサートに置き換えて、使用しているライブラリが更新された動作を得るようにします(既にコンパイルされている場合は遅すぎます)。
ISCのBIND(インターネットに動力を与えるDNSサーバ)のようなプロジェクトでは、DoS自体がアサーションを持っています(彼ら自身のアサーションがあり、Posixアサートを使用しません)。自発的なDoSのためにBINDに対していくつかのCVEがあります。自分でDoSするのは、 "デバッグ中のプログラムを中断させる"ことです。
完全性のために、Microsoft Foundation Classs(MFC)は以前は間違いを早期に発見するために16,000または20,000のアサーションを使用していましたが、それは1990年代後半か2000年代半ばに戻った。私は今日の状態ではありません。
のAPI
一部のAPI意図的"デバッグおよび診断"のために構築されているものが存在します。他のAPIも、本番環境で必ずしも安全に使用することはできませんが、そのために使用できます。
(意図的に作成された)前者の例は、LoggingとDebugPrint
APIです。 Appleはそれを使って、ユーザーのFileVaultパスワードとキーを出力することに成功しました。またos x filevault debug printを参照してください。
後者(生産には安全でない)の例は、Windows IsBadReadPointer
とIsBadWritePointer
です。それは競争状態に苦しんでいるため、生産上安全ではありません。しかし、あなたは特別な精査をしたいので、通常は開発のためにうまくいく。
セキュリティレビューと監査を実行する際には、必須ではないすべてのログを削除するよう尋ねたり、推奨することがよくあります。実行時にロギング・レベルを変更できないようにしてください。アプリが制作になると、デバッグの時間が終了します。すべてを記録する理由はありません。
ライブラリ
時には診断のデバッグを支援するために使用する特別なライブラリがあります。 LinuxのElectric FenceとMicrosoftのCRT Libraryがあります。どちらもAPIを備えたメモリチェッカです。この場合、リンクするコマンドも異なります。
オプション
時々、デバッグおよび診断を支援するために、追加のオプションや定義を必要としています。 GlibC++と-D_GLIBCXX_DEBUG
が気になります。もう1つはコンセプトチェックです。これは以前は-D_GLIBCXX_CONCEPT_CHECKS
の定義で有効になっていました。そのブーストコードとその壊れたので、あなたはそれを使用すべきではありません。このような場合、コンパイルフラグは異なります。
私がよく笑うもう1つは、NDEBUG
が定義されていないリリースビルドです。これにはDebianとUbuntuがポリシーの問題として含まれています。 NSA、GHCQなどの3文字代理店は、機密情報(サーバーキーなど)を取得し、暗号化を取り除いて(保護されていないファイルに書き込む)、機密情報を出力してくれてありがとうレポートなど)。値が明示的に初期化されていないとき
初期
いくつかの開発環境では、特別なビットパターンで初期化を行います。コンパイラやリンカのようなツールの本当の機能です。 Microsoftのツールが思い浮かぶ。 When and why will an OS initialise memory to 0xCD, 0xDD, etc. on malloc/free/new/delete?を参照してください。GCCには機能要求がありましたが、これまで何も完了していないと思います。
私は、プロダクションDLLを逆アセンブルして、デバッグDLLを出荷していることを知っているので、私が頻繁に笑います。リリースDLLには、開発チームがクリアできなかったメモリエラーがあることがよくあるので、私は笑います。 Adobeはこれを行うことで有名である(AppleやMicrosoftのようなオペレーティングシステムを提供していないにもかかわらず、Adobe supplies some of the most insecure software on the planet)。
#ifdef _DEBUG
check that error didn't occur...
SerialPrint("Error occurred")
#endif
それは私が泣きたくなる、あなたはまだ2016年GDBでこれを行う必要がある(だった?)あなたがprintfの年代を使用する必要がありますので、Aarch64、X32およびS/390の下で壊れましたコードをデバッグします。
多くの場合、他のマクロで囲まれたシーケンスとよく似ています。実際には、C++標準に指定されているようなものがあります。['assert'](http://en.cppreference.com/w/cpp/error/assert) –
たとえば、Microsoft Visual C++の標準ライブラリをコンパイルするとデバッグモードでは、コンテナ( 'std :: vector'など)とイテレータの拡張データ構造を使用してeにします。 g。無効化されたイテレータを使用して検出を支援します。 – ach