• ベストアンサー

DLLのマルチスレッドの動作について

今、DLLについて勉強しているのですが動作について、不明点があり質問しています。 単純にDLL内に下記のようにMyFuncという関数があったとします。 (コンパイルは/MTを付けています) MyFunc (){ int i; for(i=0;i<10;i++){ printf("%d\n"); } } これをDLLを呼び出すアプリから複数のスレッドで呼び出したとき、それぞでのスレッド毎に、カウントが増えていきます。 DLLはメモリ共有されると思っているのですが、そうではないのか、いまいちわからない状態でご教授いただければと思っています。 このカウントが別々に増えるのは、コードの領域とデータの領域が別ベルだからと考えればよいのでしょうか? コードは同じ領域を使用して、データは別の領域を使用しているのでしょうか? 次にここで使用しているint iをグローバル変数にすると、カウントはスレッド毎に共有されてしまいます。 グローバル変数にすると、この場合のint iはコードの領域に置かれるということなんでしょうか? ちょっと、的を得ていない質問かもしれませんが、何卒、よろしくお願いいたします。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

>>このカウントが別々に増えるのは、コードの領域とデータの領域が別ベルだからと考えればよいのでしょうか? ほぼ、そう思って問題ないかと思います。 補足するとスレッドが生成された時に、生成したスレッドに対し新しいスタック領域が生成され割り当てされます。 MyFunc内で宣言された変数iは各スレッドのスタック領域に確保されるため、それぞれのスレッド毎にカウントされることになります。 >>グローバル変数にすると、この場合のint iはコードの領域に置かれるということなんでしょうか? コード領域ではありませんが、固定領域に置かれます。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (1)

  • tana_y
  • ベストアンサー率41% (7/17)
回答No.2

マルチスレッドやDLLとは関係なく、 関数内で変数を宣言すると、関数内でしか扱えません。 スレッドAとBからMyFuncをコールしても、動的にデータ領域を確保(スタック) し、関数を出ると開放されるので独立した存在で影響を与えません。 仮にシングルスレッドで二回MyFuncをコールしても各カウンタ変数は独立しています。 変数のスコープを認識すると理解できると思います。

参考URL:
http://www.geocities.jp/ky_webid/c/022.html
全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • マルチスレッドの疑問点と配列について

    こんばんわ。 VC++.NET2003を用いて、C言語プログラミングを行っています。以下に質問内容をまとめます。 1.現在、マルチスレッドを行っています。マルチスレッドの注意点として、 ・スレッドが複数同時に処理(現在2スレッド)され、それぞれのスレッドで同一のグローバル変数をアクセスする。 ・各スレッドで使用しているスタティック変数はプロセスとして1つの領域に確保される。 と記述されていました。 現在、2スレッド動かしているのですが、2スレッド共通で使用したい変数がある場合は、グローバル変数として宣言してよいのでしょうか? スタティック変数というのは、 static int i を指すのでしょうか・・・・初心者的発言で申し訳ありません。 次にもう一つ質問させていただきます。 配列を整数型で10000要素、静的に用意します。 これを、memset関数ですべての番地に0を初期値として入れておきます。 たとえば、9000という数字があった場合、9000番に整数値9000を格納する。また、56では56番に56を格納する。 そして、最終的に10000要素を走査し0の場所をカウントする。 ということは可能でしょうか?もしよろしければ、サンプルを教えていただきたいと思っています。 よろしくお願い致します。

  • JAVAのマルチスレッドの共有変数についての質問

    JAVAのマルチスレッドの共有変数についての質問です。 スレッドを2つ作ってその2つのスレッド共有の配列を作りたいのですがどうすれば良いのでしょうか。 コードは以下のとおりです。 public class testes extends Thread { int n; int a[]={10,10}; public testes(int n){ this.n = n; } public static void main(String[] args) { // TODO 自動生成されたメソッド・スタブ testes t1 = new testes(0); testes t2 = new testes(1); t1.start(); t2.start(); } public void run(){ a[n] =n; System.out.println(a[0]+","+a[1]); } } 実行すると(0,10)もしくは(10,1)が表示されます。 このとき(0,1)と表示するにはどうすれば良いのでしょうか。

  • マルチスレッド化。

    今とても大きな配列を使用し、長時間処理をするプログラムを組んでいます。元々処理時間に1時間を要するプログラムを2分で処理を完了するまでに仕上げました。 しかし、探究心はおさまらずもう少し高速化に挑みたいと考えています。 過去に「猫でもわかる」のSDK第1章と2章を学び、マルチスレッドのプログラムをSDKで組んだことがあります。それを利用してマルチスレッド化を実現したいと考えています。 言語はCでVisualStudio2005を使用しています。 *疑問1   SDKの場合WinMain関数とプロシージャからの実行で_beginthread関数を記述すれば処理が開始されます。 Cでもmain関数内に記述すれば、SDKと同様に処理できるのでしょうか? *疑問2 _beginthread関数の引数に関してです。 第1引数にvoid型のスレッド関数、第2引数に0?、そして第3引数にはスレッド関数に渡すデータの引数を記述すると把握しているのですが、渡したいデータは複数あり、***型と**型、それに変数を数個とスレッド関数に渡したいデータだらけなのですが、どのように記述すればよいでしょう? *疑問3 2つのスレッドを作成しようと考えていますが、その2つのスレッドで1つの大きな配列を共有して処理したいと考えています。 そのため、スレッド間の同期が必要になるわけですが同期の種類にもクリティカルセクションやミューテックス、イベントと豊富でどれを使用すれば良いのか迷ってしまいます。厳密に同期を取り処理をするにはイベントが一番良いと考えています。 これらの疑問に答えられる方はアドバイスをよろしくお願いします。

  • マルチスレッドでのインスタンス変数

    http://itpro.nikkeibp.co.jp/article/COLUMN/20070820/279950/ このサイトに以下ような趣旨の記述があり、信じられない気持ちでいっぱいです。 「マルチスレッドのケース(たとえばサーブレットでは、)インスタンス変数はヒープ領域に 保持されるので、複数のスレッドからアクセスされるので情報が書き換えられる場合がある」 信じられないのは、インスタンス変数が書き換えられるということです。 サーブレットではインスタンス変数が共有されるのは理解していますが、 サーブレットから呼ばれるインスタンスで定義されているインスタンス変数も それに該当するのでしょうか。 それとも、サーブレット内だけの話で、サーブレットから呼ばれるインスタンスでは インスタンス変数は独立していると思ってよいでしょうか。 後者の認識ですが、こういう書き方をされると、サーブレットから呼ばれた先でも インスタンス変数が共有されると読めて、怖くて仕方ないです。

    • ベストアンサー
    • Java
  • マルチスレッドでバグが発生します

    実際のプログラムでバグが出たので、簡易化したプログラムでテストしてみましたがどこが悪いのか分かりませんでした。 #include <WinSock2.h> #include <vector> #include <process.h> #include <algorithm> #include <stdio.h> using namespace std; CRITICAL_SECTION cs; unsigned __stdcall Login( void * ); int main() {     vector<unsigned int> thID;     vector<HANDLE> hTh;     for( int i=0 ; i<10 ; i++ )     {         printf( "メインスレッド:%d\n", i );         if( (i%2) == 0 )         {             thID.push_back( i );             hTh.push_back( (HANDLE)_beginthreadex(NULL, 0, Login, &i, 0, &thID[i]) );         }     }     while(1)     {         for( int i=0 ; i<10 ; i++ )         {             if( hTh[i] != NULL )             {                 CloseHandle(hTh[i]);             }         }         char a[2];         scanf( "%c", a );         if( strcmp( a, "X" ) == 0 )         {             return 0;         }     } } unsigned __stdcall Login( void *Num ) { int *a = (int *)Num; for( int i=0 ; i<10 ; i++ ) { printf( "サブスレッド%d:%d\n", *a, i ); } return 0; } 出るエラーは以下のようになります Windows によって Server.exe でブレークポイントが発生しました。 ヒープが壊れていることが原因として考えられます。Server.exe または読み込まれた DLL にバグがあります。 あるいは、Server.exe がフォーカスを持っているときに、ユーザーが F12 キーを押したことが原因として考えられます。 可能であれば、出力ウィンドウに詳細な診断情報が表示されます。 if( (i%2) == 0 ) をコメントアウトするとエラーは出ません また、共に 表示される例として(見やすいように空行あり) 以下のように、 スレッド番号が+1されていたり(A) 各スレッド内のループ回数が直前のスレッドの回数を引き継いでいたり(B) スレッドのループ回数が初期化されていたり(C) 呼び出されてないはずのスレッドが起動していたり(D) します メインスレッド:0 メインスレッド:1 サブスレッド1:0 ・・・・・・A(本来はサブスレッド0のはず) サブスレッド1:1 メインスレッド:2 サブスレッド2:3 ・・・・・・B(本来はサブスレッド2:0のはず) サブスレッド2:4 サブスレッド2:5 サブスレッド1:0 ・・・・・・C(本来は1:3のはず) サブスレッド1:1 サブスレッド2:0 サブスレッド3:0 ・・・・・・D(本来はまだ起動してないはず) サブスレッド3:1 メインスレッド:3 どこを直せばいいか教えてください

  • マルチスレッドプログラム

    いつもお世話になっております。 今回はマルチスレッドプログラムについてお聞きしたいです。 マルチコアCPUを使ってたとえば下記のようなことをしたいときに for (int i = 0; i < 1000000; i++) { sum += i; } このまま計算するよりもいくつかスレッドを作って、計算量を分散させてから最後に足してやるほうが早いと思いまして、 現在Core2Quadが手元にありましたのでスレッドを4つ作って スレッド1で0から250000まで スレッド2で250001から500000まで スレッド3と4も同様にして実際にやってみたのですが スレッドなしの状態よりも倍くらい時間がかかってしまうようになってしまいました。 計算結果は同じになり、CPU使用率もシングル時が25%、マルチ時が100%になっているので意図したようにはできていると思います。 GetProcessAffinityMaskを使って、各スレッドにひとつづつコアを割り当てても同様でした。 実際に時間が4分の1に近くなると思っていたのですが2倍かかってしまったので不思議です。 どなたか上記のことを思惑通りに動かせそうな方法をご存知の方はご教授願います。 プログラムは全部は無理ですが重要そうなところは下記のとおりです。 スレッド作成部分 {   DWORD dwStart = ::timeGetTime();   _thread_handle[0] = (HANDLE)::_beginthreadex(NULL, 0, thread_first, NULL, CREATE_SUSPENDED, &_thread_first_id);   _thread_handle[1] = (HANDLE)::_beginthreadex(NULL, 0, thread_second, NULL, CREATE_SUSPENDED, &_thread_second_id);   _thread_handle[2] = (HANDLE)::_beginthreadex(NULL, 0, thread_third, NULL, CREATE_SUSPENDED, &_thread_third_id);   _thread_handle[3] = (HANDLE)::_beginthreadex(NULL, 0, thread_forth, NULL, CREATE_SUSPENDED, &_thread_forth_id);   for (int num = 0; num < 4; num++)   {     ::ResumeThread(_thread_handle[num]);   }   ::WaitForMultipleObjects(4, _thread_handle, TRUE, INFINITE);   for (num = 0; num < 4; num++)   {     ::CloseHandle(_thread_handle[num]);   }   DWORD dwEnd = ::timeGetTime(); } 各スレッド部分 { HANDLE hCurrent = ::GetCurrentProcess(); DWORD pamask, samask, patmp = 0; int nRet = ::SetProcessAffinityMask(hCurrent, 0x0001); ::GetProcessAffinityMask(hCurrent, &pamask, &samask); DWORD dwStart = ::timeGetTime(); _result1 = 0; for (int multi = 0; multi < _multi; multi++) {   for (DWORD i = 0; i < 100000/4; i++)   {     _result1 += i;   } } DWORD dwEnd = ::timeGetTime(); time1 = dwEnd - dwStart; ::_endthread(); return 0; } 開発環境は WindowsXP SP3 VisualStudio6.0 ATL/WTLです。

  • C++開発アプリとDLLとで同じ領域のデータを共有するには

    お世話になっています。 ただいまC++でアプリ開発をしていますが、C++で作成したアプリと、DLLとで同じ領域のデータを共有して使いたいと思っています。 C++で外部で宣言した変数(構造体)のデータをDLLで参照して、内容を変更、C++アプリで変更した内容を参照して処理すると言う具合です。 DLLの方は既に作成済みで、引数としてC++アプリのデータを渡すことが出来ないので、どうにかしてC++で宣言した変数を参照したいのですが。 よろしくお願いします。

  • DLLはアドレスを共有する?

     CでWindowsプログラミングの勉強をしています.そこでDLLについての質問なのですが,ある本で「DLLは複数のプログラムが共有し,ひとつのDLLはひとつしかメモリ上に配置されない」という文章を読みました.プログラムはDLLの配置されてあるアドレスを元に,DLL内の関数を実行するのだと考えれば納得はいきましたが,よく考えたらおかしいと思いました.  それは「変数,関数」の取り扱いはどうなるのか,ということです.C言語で物理メモリアドレスを見る方法がわからないので何とも言えませんが,試しに,DLL内に次のような関数MyFunctionを用意し,このDLLを取り込むプログラムを同時に2つ走らせ,MyFunctionを何度も呼んでDll1_Variableの値を増加させていきました. LIBSPEC int MyFunction(LPCWSTR str) { static int Dll1_Variable=0; Dll1_Variable++; _tprintf(_T("%d\n"),Dll1_Variable); return 0; }  もしDLLが共有されているのならば,Dll1_Variableの値は2つのプログラムから同時に更新されると思うのですが,実際には2つのプログラム上でまったく独立(つまり各プログラムごとに1,2,3,...というように)増加していきました.こうなるとDLLって本当に共有されているのかという,不信感が出てきてしまいます.  なんだか重大な勘違いをしている気がしてなりませんが,上記のプログラムがなぜ独立に変数が増加していくのか,「DLLが共有される」というのは実際にはどういう仕組みになっているのか,ご存知の方がいらっしゃったらご教授ください.わかりにくい質問ですみません.よろしくお願いします.

  • マルチスレッド処理でOutOfMemory

    こんにちは。現在javaによるバッチ処理で、一定時間ごとにメールを受信してその内容を解析してDBに登録する、と言うプログラムを組んでいます。 メールの受信は、POPアカウントごとにサーバに接続して受信すると言う仕様にしなくてはなりません。このため、POPアカウントごとにThreadを生成して並行処理で複数のPOPサーバに同時に接続してメールを受信する、と言う流れにします。 ここで問題なのが、タイトルのとおり、OutOfMemorryエラーが発生してしまうことなんです。おそらくThreadの生成の仕方に問題があるのではないか、と言う考えにいたりましたが、解決策がわからないので、ここで質問させていただきます。以下が、そのコードを簡略化したものです。以下の一連の処理が一定時間ごとに行われる想定です。 ~中略~ // POPアカウント情報をリストへ格納 List popAccountList = getPopData(); for(int i = 0; i < popAccountList.size(); i++){ PopAccount data = popAccountList.get(i); // PopAccountの一意のIdをスレッドにセットして生成 PopGetThread thread = new PopGetThread(data.popData); // スレッドの中で、メール受信処理が行われる。 thread.start(); try{ // 1つのスレッドが処理を終えるまで待つ thread.join(); }catch(InterruptedException ie){ } } ~続く~ こういう具合で、この処理を一定時間ごと(分単位)に、繰り返します。Runtime.getRuntime.totalMemory()などで、確認すると、周期処理が進むごとに、徐々に使用メモリが増えていってしまい、やがてOutOfMemoryになります。Threadがメモリを食いつぶしていることが原因ではないかと思うのですが、このような場合、どう解決すればいいのでしょうか。どなたかご教授いただけませんでしょうか・・お願いします。

    • ベストアンサー
    • Java
  • マルチスレッド下でのインスタンス変数・クラス変数

    よろしくお願いします。  マルチスレッド下で動作するクラスを作成しています。データにアクセスするためのオブジェクトを クラスのフィールド値として保持し、使い回しを行いたいと考えています。このデータアクセスオブジェクト(以下Dao)内では特にフィールドは使用せず、全てローカル変数のみで動作するようになっています。Dao自体は初回のクラス生成時にstatic処理にてフィールドにセットされます。  このDaoを保持するフィールドは、staticなクラス変数が良いのか、インスタンス変数として保持する方が良いのか迷っております。  クラス変数ならばPermanent領域をオブジェクト1つ分のメモリ使用で済み、インスタンス変数だとスレッド毎にheapを使い、処理数が増えるとメモリ圧迫しちゃう?と安易に考えてしまったりしています。  ご意見・ご助言よろしくお願い致します。

    • ベストアンサー
    • Java