0

main関数内に構築するクラスがいくつかあります。それらはローカル変数で定義されているため、メインリターンの後にそれぞれ分解されます。しかし、私は避けたい奇妙な出来事に気づきました。クラスの1つのメモリレイアウトを変更し(フィールドを追加または変更することにより)、リンクする前に変更したクラスのみを再コンパイルすると、セグメンテーション違反または無効なポインタが発生します(プログラムに加えた変更によって異なります) 。メインファイルも再コンパイルしてもエラーはありません。

メインファイルにヘッダーを含めると、各クラスに一定量のメモリが割り当てられると想定されるため、これが発生することはかなり確実ですが、この値はmain.oがコンパイルされてから変更されているため、プログラムが閉じたときにオブジェクトを分解するときに、そこにないメモリを探します。

現時点ではメインファイルの再コンパイルは問題ではありませんが、プロジェクトが大きくなるにつれて他のファイルでこれに遭遇するのではないかと心配しています。エラーを回避するために毎回再コンパイルすることは望ましくありません。これらのエラーを回避する簡単な方法はありますか?

4

4 に答える 4

1

一部のクラス メンバー (コンストラクターやデストラクタなど) がインライン化され、一部がインライン化されない可能性がかなり高く、各セットはオブジェクト ポインターからの異なるオフセットを使用して特定のメンバーを検索します。

mkdepヘッダーを変更すると、そのヘッダーを含むすべてのファイルが再コンパイルされるように、適切なソースとヘッダーの依存関係を持つメイクファイルを生成するようなものを使用することを検討してください。

または、すべてのクラス メンバー定義 (コンストラクター、コピー コンストラクター、および代入演算子を含む。この場合は何も自動生成されません) をクラスのソース ファイルに保持することを選択して、実質的にインライン化を禁止することもできます。ほとんどの場合、この問題を回避するにはこれで十分ですが、(わずかな) パフォーマンス コストがかかります。(また、データ メンバーをクラスに追加すると、オブジェクトのサイズが大きくなり、すべてのデータ メンバー アクセスに一定レベルの間接性を追加するpimpl イディオムを追加で使用しない限り、これは役に立ちません。)

于 2013-03-21T19:16:32.610 に答える
1

いいえ。クラスのレイアウトが変更された場合は、そのクラスを使用するユニットを再コンパイルする必要があります。

于 2013-03-21T19:16:40.887 に答える
0

cdhowie の回答を読んだ後、mkdep を調べ始めましたが、そのようなプログラムは廃止され、同じことを行うコンパイラ フラグに置き換えられたようです。メイン プログラム (srcpath のコード) とテスト (testpath のコード) の両方をコンパイルしてテストを実行するメイクファイルの本体を含めました。この間に、2 つの個別の依存関係ファイルが作成されます。1 つはメイン用、もう 1 つはテスト用です。

src = $(shell cd $(srcpath); find ./ -name "*.cpp")
testsrc = $(shell cd $(testpath); find ./ -name "*.cpp")
obj = $(src:%.cpp=%.o)
testobj = $(testsrc:%.cpp=%.o)
head = $(shell cd $(srcpath); find ./ -name "*.h")
testhead = $(shell cd $(testpath); find ./ -name "*.h")
skip_files = ./main.o

makedep = $(shell $(cpp) $(cflags) -MM -MT '$(patsubst $(srcpath)%.cpp, $(objpath)%.o, $(file))' $(file) >> .depend)
makedeptest = $(shell $(cpp) $(cflags) -MM -MT '$(patsubst $(testpath)%.cpp, $(testobjpath)%.o, $(file))' $(file) >> .dependtest)

all: main Test

Test: .dependtest $(addprefix $(testobjpath),$(testobj))
    @echo "Linking Tests"
    @$(cpp) $(lflags) -o $(testbin) $(addprefix $(testobjpath), $(testobj)) $(addprefix $(objpath), $(filter-out $(skip_files),$(obj)))
    @./$(testbin)

.dependtest: $(addprefix $(testpath), $(testsrc)) $(addprefix $(testpath), $(testhead))
    $(shell rm -f .dependtest)
    $(foreach file,$(addprefix $(testpath), $(testsrc)), $(makedeptest))

$(addprefix $(testobjpath), %.o): $(addprefix $(testpath), %.cpp)
    $(cpp) $(cflags) -c -o $@ $<

main: .depend $(addprefix $(objpath), $(obj))
    @echo "Linking Program"
    @$(cpp) $(lflags) -o $(bin) $(addprefix $(objpath),$(obj))

.depend: $(addprefix $(srcpath), $(src)) $(addprefix $(srcpath), $(head))
    $(shell rm -f .depend)
    $(foreach file, $(addprefix $(srcpath), $(src)), $(makedep))

$(addprefix $(objpath), %.o): $(addprefix $(srcpath), %.cpp)
    $(cpp) $(cflags) -c -o $@ $<

clean:
    -rm $(testbin) $(bin) $(addprefix $(objpath),$(obj)) $(addprefix $(testobjpath),$(testobj))

-include .depend
-include .dependtest
于 2013-03-22T14:51:26.477 に答える
-3

コマンド ラインでコンパイルする代わりに、IDE を使用します。

于 2013-03-21T19:15:57.647 に答える