こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

大きな配列を使うには?

BCCにJavaからポーティングしましたが、配列 int array[max]で、150000程度の大きさを超えると、メモリ不足で止まってしまいます。BCCかリンカのオプションで、ヒープやスタックサイズを変更する具体的な方法、または、大きな配列を上手く使う方法を教えてください。(プログラムはこんな感じ。)

#define max_array 140000 /* このサイズを変更したい */
void main() {
char array[max_array] ;

この後、ヒープも使うのですが、(そのメモリ確保も必要)そこまで
行かない。。。。

(MSのVC++2005でも、同様になりました。)

10数年ぶりにプログラムをしている初心者です。
よろしくお願いします。

投稿日時 - 2006-10-21 15:15:32

QNo.2487531

すぐに回答ほしいです

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

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

投稿日時 - 2006-10-21 16:03:23

お礼

早速ご返事ありがとうございます。
#define max_array 140000 /* これを大きくしたい */
char array[max_array] ;  /*(追加) 外部(大局)変数として宣言 */
void main() {
extern char array[max_array] ; /*(変更)*/

としたところ、難なく実行できてしまいました。ありがとうございます!!!
「目から鱗(うろこ)」とはこんな状況の事でしょうか。。。

向学のために、main()の内部で宣言するのと、外部で宣言するのと何が違うのでしょうか??? 教えていただけると幸いです。
ご回答の文面だと、externでは、ヒープ(の一番最初の領域に静的に確保される)との事ですが、main()の静的変数だったらスタック側で同じような状況になると思われます。
BCC(やCコンパイラ全般)では、スタックサイズに上限があるという事でしょうか?

よろしくお願いいたします。

投稿日時 - 2006-10-21 21:02:37

このQ&Aは役に立ちましたか?

2人が「このQ&Aが役に立った」と投票しています

回答(7)

ANo.7

> (でも、固定サイズの変数なので、コンパイル時にエラーかワーニングを出すか、
-- snip --
>くれたのに。。。と思うのは、年寄りだけでしょうか??))

ベンダが独自にどこまで親切に作りこむかってところだと思いますが、
C/C++コンパイラは「プログラマの道具」としてプログラマの意図を極力制限しないですし、
C/C++はそういうのを保護してくれない/関知しない言語なので…そういうものじゃないでしょうか。

固定サイズとは言っても、関数内ローカルの自動変数なので、
リンカオプションでサイズを増やる以上コンパイラはエラーにしないでしょうし、
リンカは関数内の消費スタックをチェックしてエラーになどしないということだと思います。

「スレッド毎に」デフォルト1MBなので、全体を単純に合計されると余計なおせっかいになります。
また、Windowsで動的にスレッドを作成する際は「スレッド起動時にスタックサイズを指定可能」です。
静的なリンカに実行時の関数呼び出し関係を洗えというのは酷ではないでしょうか。
ということで、実行時例外になるのは仕方ないと私は思います。

C/C++は、ファミリー向けオートマ車ではなく、レース仕様のマニュアル車だと思いますし、
「書いた通りにそのまま動く」のが極限の環境では利点でもあると思いますので、
組込とかも視野に入れた言語として、本来「親切に(勝手に)何かをしない」ものだと思います。
PC環境なら、親切に/安全に使える別言語もありますので、住み分けなんじゃないでしょうか。

投稿日時 - 2006-10-22 18:56:22

お礼

>C/C++コンパイラは「プログラマの道具」としてプログラマの意図を極力制限しないですし、
>C/C++はそういうのを保護してくれない/関知しない言語なので…そういうものじゃないでしょうか。

賛成です。
C/C++の方向性は、そういう物だと思っています。(賛否はありますが、イヤだったらJavaでがっちりガードすれば良い。)

私が勘違いしてしまったは、BCCがWindow(Win32)前提だったという事を知らなかったからだと思います。
(gccは、どうなっているのかな?というのは興味ありますが、今回のテーマでは無いので止めときます。)

いろいろとご親切なアドバイスありがとうございました。

投稿日時 - 2006-10-22 22:54:22

ANo.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: も同様

投稿日時 - 2006-10-22 17:29:03

お礼

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

投稿日時 - 2006-10-22 22:40:02

ANo.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()の場合は開放し忘れに注意が必要です。

投稿日時 - 2006-10-22 08:19:11

ANo.4

> BCC(やCコンパイラ全般)では、スタックサイズに上限があるという事でしょうか?
勿論あります。BCCやVCは、デフォルトでスレッド毎に1MB確保します。
スレッド全体でこのサイズなので「150K*4=600KB」とか安易にとると、他の一時変数等とあわせてスタックがオーバフローする可能性は高いでしょう。
うまく使う方法は、Javaベース(OO)なのでしょうから、new等で動的確保することでしょうか。
既出ですが、スタックに置くのはお勧めしません。

C/C++のメモリ配置は実装依存/環境やコンパイラ次第ですが、
一般的にはスタックと、静的領域と、動的領域(ヒープ)の三種があると考えて問題になることはそう無いと思います。

ちなみに、#1でも#2でも回避可能なので、設定がうまくできてないだけかと思います。

投稿日時 - 2006-10-22 01:44:36

お礼

ご回答ありがとうございます。
デフォルトのスタックサイズが1MBという事は初めて知りました。
ありがとうございました。

元々は、newで動的確保をしていたのですが、細かく確保と解放を繰り返す仕様なので、この部分のオーバーヘッドを減らすために、わざわざ配列を使ってみました。

念のため、mallocを試してみても、やはりデフォルトのヒープ領域が少ないようで、うまくいきませんでした。
リンクオプション(S:xxxx H:xxxx)は、設定の方法が良くわからずGiveUpでした。
BCCの詳細なオンラインマニュアルが見つけられなかっただけですけど。(泣)

(でも、固定サイズの変数なので、コンパイル時にエラーかワーニングを出すか、(もっと親切に)確保するスタックサイズを増やすのが自然なように思います。(昔のホストコンピュータのコンパイラはちゃんとやってくれたのに。。。と思うのは、年寄りだけでしょうか??))

投稿日時 - 2006-10-22 16:44:00

ANo.2

BCCをインストールしたディレクトリにヘルプファイル
Help\bcb5tool.hlp
があります。

それによると、リンカオプションで

/S:xxxxアプリケーションのスタックの予約サイズを 16 進値で指定する
/Sc:xxxxアプリケーションのスタックのコミットサイズを 16 進値で指定する

とあるので、それでうまくいかないでしょうか?

投稿日時 - 2006-10-21 15:53:17

お礼

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

投稿日時 - 2006-10-21 21:10:18

ANo.1

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

投稿日時 - 2006-10-21 15:28:53

お礼

アドバイスありがとうございます。

mallocはやってみましたが、上手くいきませんでした。

ありがとうございました。

投稿日時 - 2006-10-21 21:11:25

あなたにオススメの質問