私は専用のLinuxCentOSシステムでうまく機能しているプロジェクトに取り組んできました。
一般的な考え方は、ctypesを使用してCで記述された共有ライブラリを呼び出すPythonワークフローマネージャーがあるということです。正常に動作します。
ただし、開発目的でプロジェクトのローカルインスタンスを用意する必要があります。Windows7でVMWareを使用してLinuxMint仮想マシンをセットアップしました。ほとんどの場合、すべてが正常に機能します。
問題は、共有ライブラリの1つで関数を呼び出すと、1つのモジュールがセグメンテーション違反でクラッシュすることです。通常、これは問題ありません。専用のLinuxマシンでは、「gdb python corename」のようなものを使用すると、クラッシュした場所を正確に確認して問題を解決できます。
ただし、ローカル設定では問題が発生します。私が最も気付くのは、GDBが正しいメモリアドレスを報告しないことです。これは巨大なプロジェクトなので、すべてのコードを投稿することはできませんが、概要を説明します。
Pythonモジュールは、文字列である「file_path」変数を作成します。まず、これを特定の共有ライブラリに渡してファイルをロードします。コマンドを実行すると、Pythonで
hex(id(file_path))
'46cb4ec'のようなものを返します。最初の共有ライブラリであるCでは、最初に
printf("file_pathaddress = %x\n", &file_path[0]);
'file_path address = 46cb4ec'を出力します。これは、Pythonの' id()'関数を介して取得したものと同じです。これは予想されることだと思います...?
とにかく..これと同じ変数を別の共有ライブラリに送信しましたが、この呼び出しですぐにクラッシュします。コアファイルを分析すると、関数内の行ではなく、関数呼び出し自体でクラッシュすることがわかります。ただし、奇妙なことに、次のような出力が表示されます。
Program terminated with signal 11, Segmentation fault.
#0 0x00007f124448c9fc in seam_processor (irm_filename=<error reading variable: Cannot access memory at address 0x7fff5fab51b8>,
seam_data_path=<error reading variable: Cannot access memory at address 0x7fff5fab51b0>,
full_data_path=<error reading variable: Cannot access memory at address 0x7fff5fab51a8>, ranges=<error reading variable: Cannot access memory at address 0x7fff5fab51a0>,
job_id=<error reading variable: Cannot access memory at address 0x7fff5fab519c>, job_owner=<error reading variable: Cannot access memory at address 0x7fff5fab5198>,
y_tile_in=1, x_tile_in=1, fc_int=10650000000, atmos_props=..., surf_props=..., extra_props=<error reading variable: Cannot access memory at address 0x7fff5fab5190>,
gascalc_ftype=513, len_gas_sectrum=16, vect_spec_fq=<error reading variable: Cannot access memory at address 0x7fff5fab5188>, surfscat_theta_inc_vector_size=6,
surfscat_theta_inc_vector=<error reading variable: Cannot access memory at address 0x7fff5fab5180>, surfscat_phi_inc_vector_size=6,
surfscat_phi_inc_vector=<error reading variable: Cannot access memory at address 0x7fff5fab5178>, surfscat_theta_scat_vector_size=6,
surfscat_theta_scat_vector=<error reading variable: Cannot access memory at address 0x7fff5fab5170>, surfscat_phi_scat_vector_size=6,
surfscat_phi_scat_vector=<error reading variable: Cannot access memory at address 0x7fff5fab5168>) at src/seam_processor.c:47
したがって、私が理解できないのは、GDBがこれらのメモリアドレスをそのように報告している理由です。この場合、「irm_filename」変数はPythonが「file_path」として渡したものであるため、そのアドレスは他のライブラリとid()関数が報告する0x46CB4ECである必要があります。なぜ違うのですか?ただし、奇妙なことに、「y_tile_in」のように、一部の変数は問題ありません。gdbで行う場合:
(gdb) print &y_tile_in
$1 = (int *) 0x7fff60543f80
したがって、このメモリアドレスを読み取ることはできますが、これはPythonのid()が報告するもの、またはアドレスの同様のC printf()がクラッシュしないライブラリで報告するものと同じではありません。また、これらのメモリアドレスは本当に大きな数であり、私が持っているメモリの量よりもはるかに大きいです...それらは実際にはどういう意味ですか?
それでは、私の質問は、ここで正確に何が起こっているのかということです。これを実行している仮想マシンでこれが実行されているという事実はありますか?マッピングは行われていますか?仮想マシンでgdbを使用する場合にやらなければならないことについて、オンラインで何も見つけることができなかったので、途方に暮れています...
誰が何が起こっているのか知っていますか?
ありがとう。
編集
それで、問題は見知らぬ人になりました。基本的に、私はライブラリから何かを行うすべてのコードをコメントアウトし、関数呼び出しを同じままにしました。これを実行し、ブレークポイントを使用してgdbで実行すると、関数呼び出しで出力されるすべてのメモリアドレスは正常であり、Python id()関数と一致し、アドレスのprintf()と一致します。
問題が何であるかを確認するために、コードのコメントを外し始めました。問題は宣言にあります:
double nrcs_h_d[MAX_NINC_S*MAX_SCAT_S];
double nrcs_v_d[MAX_NINC_S*MAX_SCAT_S];
両方の行をコメントアウトすると、クラッシュは発生しません。2行目だけをコメントアウトすれば、クラッシュは発生しません。ただし、コメントアウトされた行がない場合はクラッシュします。
奇妙なことに、MAX_NINC_SとMAX_SCAT_Sはどちらも500に等しいのです。したがって、これらの配列のサイズはわずか数メガバイトです...コードの他の場所では、数百メガバイトの配列が適切に割り当てられています。
また、上記の行を次のように置き換えた場合:
double *nrcs_h_d, *nrcs_v_d;
nrcs_h_d = (double *)malloc(MAX_NINC_S*MAX_SCAT_S*sizeof(double));
nrcs_v_d = (double *)malloc(MAX_NINC_S*MAX_SCAT_S*sizeof(double));
正常に動作しているようです...したがって、問題はスタックに割り当てすぎていることに関連しているようです。
したがって、質問は次のようになります。
なぜgdbは、これがセグメンテーション違反が発生するコードの行であると表示せず、代わりに関数呼び出しであると表示するのですか?
その割り当てが行われると、コアダンプファイルのメモリアドレスがすべて台無しになっているように見えるのはなぜですか?
ありがとう。