• ベストアンサー

大きな配列を使うには?

BCCにJavaからポーティングしましたが、配列 int array[max]で、150000程度の大きさを超えると、メモリ不足で止まってしまいます。BCCかリンカのオプションで、ヒープやスタックサイズを変更する具体的な方法、または、大きな配列を上手く使う方法を教えてください。(プログラムはこんな感じ。) #define max_array 140000 /* このサイズを変更したい */ void main() { char array[max_array] ; この後、ヒープも使うのですが、(そのメモリ確保も必要)そこまで 行かない。。。。 (MSのVC++2005でも、同様になりました。) 10数年ぶりにプログラムをしている初心者です。 よろしくお願いします。

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

  • ベストアンサー
  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.3

スタックサイズのオプションについては、既にでています(-S:)が スタックにあまり大きなメモリを確保するのはよろしくないと思います。 static にするか extern にするか malloc すれば、ヒープに確保されます。

OSAKANA99
質問者

お礼

早速ご返事ありがとうございます。 #define max_array 140000 /* これを大きくしたい */ char array[max_array] ;  /*(追加) 外部(大局)変数として宣言 */ void main() { extern char array[max_array] ; /*(変更)*/ としたところ、難なく実行できてしまいました。ありがとうございます!!! 「目から鱗(うろこ)」とはこんな状況の事でしょうか。。。 向学のために、main()の内部で宣言するのと、外部で宣言するのと何が違うのでしょうか??? 教えていただけると幸いです。 ご回答の文面だと、externでは、ヒープ(の一番最初の領域に静的に確保される)との事ですが、main()の静的変数だったらスタック側で同じような状況になると思われます。 BCC(やCコンパイラ全般)では、スタックサイズに上限があるという事でしょうか? よろしくお願いいたします。

その他の回答 (6)

  • MrBan
  • ベストアンサー率53% (331/615)
回答No.7

> (でも、固定サイズの変数なので、コンパイル時にエラーかワーニングを出すか、 -- snip -- >くれたのに。。。と思うのは、年寄りだけでしょうか??)) ベンダが独自にどこまで親切に作りこむかってところだと思いますが、 C/C++コンパイラは「プログラマの道具」としてプログラマの意図を極力制限しないですし、 C/C++はそういうのを保護してくれない/関知しない言語なので…そういうものじゃないでしょうか。 固定サイズとは言っても、関数内ローカルの自動変数なので、 リンカオプションでサイズを増やる以上コンパイラはエラーにしないでしょうし、 リンカは関数内の消費スタックをチェックしてエラーになどしないということだと思います。 「スレッド毎に」デフォルト1MBなので、全体を単純に合計されると余計なおせっかいになります。 また、Windowsで動的にスレッドを作成する際は「スレッド起動時にスタックサイズを指定可能」です。 静的なリンカに実行時の関数呼び出し関係を洗えというのは酷ではないでしょうか。 ということで、実行時例外になるのは仕方ないと私は思います。 C/C++は、ファミリー向けオートマ車ではなく、レース仕様のマニュアル車だと思いますし、 「書いた通りにそのまま動く」のが極限の環境では利点でもあると思いますので、 組込とかも視野に入れた言語として、本来「親切に(勝手に)何かをしない」ものだと思います。 PC環境なら、親切に/安全に使える別言語もありますので、住み分けなんじゃないでしょうか。

OSAKANA99
質問者

お礼

>C/C++コンパイラは「プログラマの道具」としてプログラマの意図を極力制限しないですし、 >C/C++はそういうのを保護してくれない/関知しない言語なので…そういうものじゃないでしょうか。 賛成です。 C/C++の方向性は、そういう物だと思っています。(賛否はありますが、イヤだったらJavaでがっちりガードすれば良い。) 私が勘違いしてしまったは、BCCがWindow(Win32)前提だったという事を知らなかったからだと思います。 (gccは、どうなっているのかな?というのは興味ありますが、今回のテーマでは無いので止めときます。) いろいろとご親切なアドバイスありがとうございました。

  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.6

#3>extern char array[max_array] ; /*(変更)*/ 既に、#5で指摘されていますが、この部分は不要です。 #3>main()の内部で宣言するのと、外部で宣言するのと何が違うのでしょうか??? 教えていただけると幸いです。 例えば、static で宣言した場合、関数の外と内ではスコープ(アクセスできるかどうか)が違います。 #4>mallocを試してみても、やはりデフォルトのヒープ領域が少ないようで、うまくいきませんでした。 #4>リンクオプション(S:xxxx H:xxxx)は、設定の方法が良くわからず malloc はうまくいかなかったのですね。すみません。<(_ _)> リンクオプションは、 ilink32 とすれば表示されます。 リンカにオプションを渡すには-l で指定します。 bcc32 -h -l とすれば説明が表示されます。 例 bcc32 -lS:400000 prog.c 数値は16進で指定します。 H: も同様

OSAKANA99
質問者

お礼

ありがとうございました。 今回は、externで逃げましたが基本的な事を確認できました。 後ほどテストしてみます。

回答No.5

・関数内で定義した(非静的)変数→スタック ・関数内で定義した静的変数→ヒープ(など) ・関数外で定義した変数→ヒープ 尚、同一スコープ内の変数は、extern宣言する必要はありません。 cf. int foo = 3; int main() { printf("%d\n", foo); return 0; } ・malloc()で確保したメモリ領域→ヒープ ・newで確保したオブジェクト→ヒープ ・std::vectorで確保したオブジェクト→ヒープ ある程度以上の大きさの配列は、 C++でしたら素直にstd::vectorを使うべきですし、 Javaからのポーティングならnewが判りやすいかもしれません。 但し、newやmalloc()の場合は開放し忘れに注意が必要です。

  • MrBan
  • ベストアンサー率53% (331/615)
回答No.4

> BCC(やCコンパイラ全般)では、スタックサイズに上限があるという事でしょうか? 勿論あります。BCCやVCは、デフォルトでスレッド毎に1MB確保します。 スレッド全体でこのサイズなので「150K*4=600KB」とか安易にとると、他の一時変数等とあわせてスタックがオーバフローする可能性は高いでしょう。 うまく使う方法は、Javaベース(OO)なのでしょうから、new等で動的確保することでしょうか。 既出ですが、スタックに置くのはお勧めしません。 C/C++のメモリ配置は実装依存/環境やコンパイラ次第ですが、 一般的にはスタックと、静的領域と、動的領域(ヒープ)の三種があると考えて問題になることはそう無いと思います。 ちなみに、#1でも#2でも回避可能なので、設定がうまくできてないだけかと思います。

OSAKANA99
質問者

お礼

ご回答ありがとうございます。 デフォルトのスタックサイズが1MBという事は初めて知りました。 ありがとうございました。 元々は、newで動的確保をしていたのですが、細かく確保と解放を繰り返す仕様なので、この部分のオーバーヘッドを減らすために、わざわざ配列を使ってみました。 念のため、mallocを試してみても、やはりデフォルトのヒープ領域が少ないようで、うまくいきませんでした。 リンクオプション(S:xxxx H:xxxx)は、設定の方法が良くわからずGiveUpでした。 BCCの詳細なオンラインマニュアルが見つけられなかっただけですけど。(泣) (でも、固定サイズの変数なので、コンパイル時にエラーかワーニングを出すか、(もっと親切に)確保するスタックサイズを増やすのが自然なように思います。(昔のホストコンピュータのコンパイラはちゃんとやってくれたのに。。。と思うのは、年寄りだけでしょうか??))

  • sonetea
  • ベストアンサー率26% (9/34)
回答No.2

BCCをインストールしたディレクトリにヘルプファイル Help\bcb5tool.hlp があります。 それによると、リンカオプションで /S:xxxx アプリケーションのスタックの予約サイズを 16 進値で指定する /Sc:xxxx アプリケーションのスタックのコミットサイズを 16 進値で指定する とあるので、それでうまくいかないでしょうか?

OSAKANA99
質問者

お礼

アドバイスありがとうございます。 リンカオプションは試してみましたが解決できませんでした。 (150K*4byte程度のサイズで問題になっているので、根本原因が  どこかな?という事です。)  

noname#39970
noname#39970
回答No.1

ちょっと面倒だけど malloc で取り回したらどうだろう

OSAKANA99
質問者

お礼

アドバイスありがとうございます。 mallocはやってみましたが、上手くいきませんでした。 ありがとうございました。

関連するQ&A