C++の基礎を深く学ぶ
文書ディレクトリ C++メモリ管理 LINUXプロセスセグメントおよび格納データ GCCコンパイルプロセス 動的ライブラリ静的ライブラリ区別およびGCCロードライブラリ extern-Cの結果とCPPコンパイルの違い 重荷の底層原理 コンパイル言語と解釈言語の本質的な違いと長所と短所 C++メモリ管理スタック記憶関数の戻りアドレス、パラメータ、局所変数、戻り値は、高アドレスから低アドレスへ 増加する.スタックmalloc/freeはメモリの空間を開き、低アドレスから高アドレスに 増加する.フリーストレージnew/deleteメモリ領域 を開くデータ領域データ領域は、グローバル/静的記憶領域および定数記憶領域を含む、初期化されたグローバル変数および静的変数、初期化されていないグローバル変数および静的変数、および文字列定数 を記憶する.コード領域記憶プログラムのマシンコードとプログラム命令 LINUXプロセス領域セグメントおよび格納データ
Linuxの各プロセスにはそれぞれ独立した4 G論理アドレスがあり、そのうち03 Gはユーザ状態空間、34 Gはカーネル空間であり、異なるプロセスの同じ論理アドレスは異なる物理アドレスにマッピングされる.論理アドレスセグメントは、下から上へ:コードセグメント.読み取り専用メモリ領域とコード領域に分けられ、格納文字列は定数とプログラムマシンコードと命令 である.データ・セグメント.初期化されたグローバル変数と静的変数を格納します. bssセグメント.初期化されていないグローバル変数および静的変数、および0に初期化されたグローバル変数および静的変数を格納する .スタック.プロセスがmallocを呼び出さない場合、スタックセグメントはなく、malloc/freeが開いたメモリ空間は、 上に成長する.マッピング領域.動的リンクライブラリおよびmmap関数を呼び出すファイルマッピング を格納する.スタック.関数の戻りアドレス、パラメータ、ローカル変数、戻り値を格納し、下に成長します.
GCCコンパイルプロセス前処理段階:hello.c-「gcc-E前処理、ヘッダファイル展開、マクロ置換」-->hello.i コンパイルフェーズ:hello.i-「gcc-s生成アセンブリファイル」-->hello.s アセンブリフェーズ:hello.s-「gcc-c生成バイナリファイル」-->hello.o リンクフェーズ:hello.o-「ldを呼び出してリンクする」-->a.out ダイナミックライブラリ静的ライブラリの違いとGCCロードライブラリ
静的ライブラリコンパイル期間リンク はスペースとリソースを浪費し、複数のプログラムが同じライブラリにリンクされている場合、生成された実行可能ファイルごとにライブラリのコピーがあり、必然的にシステムスペースを浪費します. 静的ライブラリを変更する必要がある場合は、そのライブラリにリンクするすべてのプログラム を再コンパイルする必要があります.
ダイナミックライブラリランタイムリンク の実行時にリンクされるため、プログラムの実行速度は よりやや遅い.ダイナミックライブラリは、プログラムの実行時にリンクされるため、ディスクにコピーを1部残すだけで、ディスク領域を節約できます.バグが見つかったり、アップグレードするのも簡単で、新しいライブラリで元のものを置き換えるだけで GCCコンパイル静的ライブラリのロードはすべてをcファイルをコンパイルする.oターゲットファイル 対が生成する.oターゲットファイルパッケージ生成静的ライブラリ ar:ライブラリ作成コマンド c:ライブラリの作成 r:メソッドをライブラリに追加 v:プロセスを表示し、 を使用しないでください.
静的ライブラリの使用 -L:パスを指定します.現在のパス を表します.-l:指定ライブラリ名
GCCコンパイル動的ライブラリのロード対が生成する.oファイル処理は、libfooという名前の共有ライブラリを生成する.so -shared出力結果が共有ライブラリタイプであることを示す -fPICは、出力ファイル を生成するためにアドレス依存コード(Position Independent Code)技術を使用することを示す.
ライブラリの使用 export変更LD_LIBRARY_PATH現在の端末の環境変数 修正/etc/ld.so.confファイル、ライブラリファイルが存在するディレクトリのパスを追加し、ldconfigディレクトリ名を実行します.このコマンドは/etc/ldを再構築します.so.Cacheファイルで 上の3種類から1つ選べば です.
extern-Cの結果とCPPコンパイルの違い C言語ファイルp.c ヘッダファイルp.h C++ファイル呼び出しC関数 コンパイル後のリンクエラー:main.cppはprint(int,int)に対して定義されていない参照である. 原因分析 p.c C言語のコンパイラgccを使用してコンパイルしました.関数printコンパイル後、シンボルテーブルの名前は_print 私たちがリンクするときはg++を使用してリンクします.つまりC++リンク方式です.プログラムはprint関数を呼び出すコードを実行すると、シンボルテーブルで_を探します.print_int_int(C++のリンク方法で探しているので、_printではなく_print_int_int)の名前を探していますが、見つからないことがわかりますので、tは「未定義の参照」 を提示します.この時点でprintに対する声明にextern「C」を加えると、g++コンパイラはC言語のリンク方式で探し、すなわちシンボルテーブルで探します.print、この時は見つけることができて、間違いを報告しません.
まとめ コンパイル後の下位解析の記号は異なり、C言語は_print,C++はい_print_int_int
じゅうかじゅうてきげんり
以上のコンパイル解析によれば,C言語にはリロードがなく,パラメータリストによって関数リロードが実現されるのはC++のみであることが分かる. C言語は、 をリロードしていません.
C言語では_Add,3つは同じなので区別できないため,C言語では関数リロードはサポートされていない. C++再負荷下位層の名前変更メカニズムは、Add関数をパラメータの個数、パラメータのタイプ、戻り値のタイプに基づいて再命名します.では、関数の再ロードを使用すると、1つの関数には複数のネーミングメカニズムがあります._Add_int_int,_Add_long_long,_Add_double_double C++では、関数宣言の前にextern"C"を付けることで、1つの関数をC言語のスタイルでコンパイルできます.
コンパイル言語と解釈言語の本質的な違いと長所と短所根本的な違い コンピュータは高度な言語を直接理解することができず、機械言語を直接理解するしかないので、高度な言語を機械言語に翻訳しなければならず、コンピュータは高度な言語の作成プログラムを実行することができない.翻訳の仕方は2つあります.1つはコンパイルで、1つは解釈です.二つの方法は翻訳の時間が違うだけです. 解釈言語はコンパイルせず、実行時に を翻訳する.コンパイル言語はコンパイル時に直接機械が実行できる言語にコンパイルされ、コンパイルと実行は別々であるが、プラットフォームをまたぐことはできない.例えばexeファイルは、後で実行するなら再コンパイルしなくてもいいので、コンパイルの結果をそのまま使えばいい(exeファイル)というように、翻訳は一度しかやっていないので、実行するときは翻訳しないので、コンパイル型言語のプログラム実行効率は と高い.
コンパイル言語のメリットとデメリット の利点 運行速度が速く、コード効率が高く、コンパイル後のプログラムは修正できず、機密性が良い の欠点 コードはコンパイルされて実行できる必要があり、移植性が悪く、互換性のあるオペレーティングシステムでしか実行できません.
解釈言語の長所と短所 の利点 は移植性が良く、解釈環境さえあれば、異なるオペレーティングシステム上で実行することができる.
の欠点 実行は環境を解釈する必要があり、実行はコンパイルよりも遅く、占有する資源も多く、コード効率が低く、コード修正後に実行でき、コンパイルプロセス を必要としない.
Linuxの各プロセスにはそれぞれ独立した4 G論理アドレスがあり、そのうち03 Gはユーザ状態空間、34 Gはカーネル空間であり、異なるプロセスの同じ論理アドレスは異なる物理アドレスにマッピングされる.論理アドレスセグメントは、下から上へ:
GCCコンパイルプロセス
静的ライブラリ
ダイナミックライブラリ
gcc -c add.c
addを生成する.o gcc -c max.c
生成max.o ar crv libfoo.a add.o max.o //libfoo.a
gcc -o main main.c -static -L. -lfoo // foo
GCCコンパイル動的ライブラリのロード
gcc -shared -fPIC -o libfoo.so add.o max.o
cp libfoo.so /usr/lib //
(推奨しない)gcc -o main main.c -lfoo
extern-Cの結果とCPPコンパイルの違い
#include
void print(int a,int b)
{
printf(" C :%d,%d
",a,b);
}
#ifndef _P_H
#define _P_H
void print(int a,int b);
#endif
#include
using namespace std;
#include "p.h"
int main()
{
cout<
じゅうかじゅうてきげんり
以上のコンパイル解析によれば,C言語にはリロードがなく,パラメータリストによって関数リロードが実現されるのはC++のみであることが分かる.
"int __cdecl Add(int,int)" (?Add@@YAHHH@Z)
"double __cdecl Add(double,double)" (?Add@@YANNN@Z)
"long __cdecl Add(long,long)" (?Add@@YAJJJ@Z)
C言語では_Add,3つは同じなので区別できないため,C言語では関数リロードはサポートされていない.
コンパイル言語と解釈言語の本質的な違いと長所と短所