BCCにJavaからポーティングしましたが、配列 int array[max]で、150000程度の大きさを超えると、メモリ不足で止まってしまいます。BCCかリンカのオプションで、ヒープやスタックサイズを変更する具体的な方法、または、大きな配列を上手く使う方法を教えてください。(プログラムはこんな感じ。)
#define max_array 140000 /* このサイズを変更したい */
void main() {
char array[max_array] ;
この後、ヒープも使うのですが、(そのメモリ確保も必要)そこまで
行かない。。。。
(MSのVC++2005でも、同様になりました。)
10数年ぶりにプログラムをしている初心者です。
よろしくお願いします。
No.2
- 回答日時:
BCCをインストールしたディレクトリにヘルプファイル
Help\bcb5tool.hlp
があります。
それによると、リンカオプションで
/S:xxxxアプリケーションのスタックの予約サイズを 16 進値で指定する
/Sc:xxxxアプリケーションのスタックのコミットサイズを 16 進値で指定する
とあるので、それでうまくいかないでしょうか?
アドバイスありがとうございます。
リンカオプションは試してみましたが解決できませんでした。
(150K*4byte程度のサイズで問題になっているので、根本原因が
どこかな?という事です。)
No.3ベストアンサー
- 回答日時:
スタックサイズのオプションについては、既にでています(-S:)が
スタックにあまり大きなメモリを確保するのはよろしくないと思います。
static にするか extern にするか malloc すれば、ヒープに確保されます。
早速ご返事ありがとうございます。
#define max_array 140000 /* これを大きくしたい */
char array[max_array] ; /*(追加) 外部(大局)変数として宣言 */
void main() {
extern char array[max_array] ; /*(変更)*/
としたところ、難なく実行できてしまいました。ありがとうございます!!!
「目から鱗(うろこ)」とはこんな状況の事でしょうか。。。
向学のために、main()の内部で宣言するのと、外部で宣言するのと何が違うのでしょうか??? 教えていただけると幸いです。
ご回答の文面だと、externでは、ヒープ(の一番最初の領域に静的に確保される)との事ですが、main()の静的変数だったらスタック側で同じような状況になると思われます。
BCC(やCコンパイラ全般)では、スタックサイズに上限があるという事でしょうか?
よろしくお願いいたします。
No.4
- 回答日時:
> BCC(やCコンパイラ全般)では、スタックサイズに上限があるという事でしょうか?
勿論あります。BCCやVCは、デフォルトでスレッド毎に1MB確保します。
スレッド全体でこのサイズなので「150K*4=600KB」とか安易にとると、他の一時変数等とあわせてスタックがオーバフローする可能性は高いでしょう。
うまく使う方法は、Javaベース(OO)なのでしょうから、new等で動的確保することでしょうか。
既出ですが、スタックに置くのはお勧めしません。
C/C++のメモリ配置は実装依存/環境やコンパイラ次第ですが、
一般的にはスタックと、静的領域と、動的領域(ヒープ)の三種があると考えて問題になることはそう無いと思います。
ちなみに、#1でも#2でも回避可能なので、設定がうまくできてないだけかと思います。
ご回答ありがとうございます。
デフォルトのスタックサイズが1MBという事は初めて知りました。
ありがとうございました。
元々は、newで動的確保をしていたのですが、細かく確保と解放を繰り返す仕様なので、この部分のオーバーヘッドを減らすために、わざわざ配列を使ってみました。
念のため、mallocを試してみても、やはりデフォルトのヒープ領域が少ないようで、うまくいきませんでした。
リンクオプション(S:xxxx H:xxxx)は、設定の方法が良くわからずGiveUpでした。
BCCの詳細なオンラインマニュアルが見つけられなかっただけですけど。(泣)
(でも、固定サイズの変数なので、コンパイル時にエラーかワーニングを出すか、(もっと親切に)確保するスタックサイズを増やすのが自然なように思います。(昔のホストコンピュータのコンパイラはちゃんとやってくれたのに。。。と思うのは、年寄りだけでしょうか??))
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()の場合は開放し忘れに注意が必要です。
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: も同様
No.7
- 回答日時:
> (でも、固定サイズの変数なので、コンパイル時にエラーかワーニングを出すか、
-- snip --
>くれたのに。。。と思うのは、年寄りだけでしょうか??))
ベンダが独自にどこまで親切に作りこむかってところだと思いますが、
C/C++コンパイラは「プログラマの道具」としてプログラマの意図を極力制限しないですし、
C/C++はそういうのを保護してくれない/関知しない言語なので…そういうものじゃないでしょうか。
固定サイズとは言っても、関数内ローカルの自動変数なので、
リンカオプションでサイズを増やる以上コンパイラはエラーにしないでしょうし、
リンカは関数内の消費スタックをチェックしてエラーになどしないということだと思います。
「スレッド毎に」デフォルト1MBなので、全体を単純に合計されると余計なおせっかいになります。
また、Windowsで動的にスレッドを作成する際は「スレッド起動時にスタックサイズを指定可能」です。
静的なリンカに実行時の関数呼び出し関係を洗えというのは酷ではないでしょうか。
ということで、実行時例外になるのは仕方ないと私は思います。
C/C++は、ファミリー向けオートマ車ではなく、レース仕様のマニュアル車だと思いますし、
「書いた通りにそのまま動く」のが極限の環境では利点でもあると思いますので、
組込とかも視野に入れた言語として、本来「親切に(勝手に)何かをしない」ものだと思います。
PC環境なら、親切に/安全に使える別言語もありますので、住み分けなんじゃないでしょうか。
>C/C++コンパイラは「プログラマの道具」としてプログラマの意図を極力制限しないですし、
>C/C++はそういうのを保護してくれない/関知しない言語なので…そういうものじゃないでしょうか。
賛成です。
C/C++の方向性は、そういう物だと思っています。(賛否はありますが、イヤだったらJavaでがっちりガードすれば良い。)
私が勘違いしてしまったは、BCCがWindow(Win32)前提だったという事を知らなかったからだと思います。
(gccは、どうなっているのかな?というのは興味ありますが、今回のテーマでは無いので止めときます。)
いろいろとご親切なアドバイスありがとうございました。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# c言語の問題です 課題1 (二分探索木とセット) 大きさ size の配列 array を考える。す 2 2023/01/10 21:08
- C言語・C++・C# プログラミングを教えて欲しいです。 配列aは、int a[9]={7,6,12,8,3,5,10,9 4 2022/12/19 23:27
- PHP 配列の値の更新方法について 1 2022/08/05 09:49
- C言語・C++・C# C言語初心者 ポインタについて、お助けください、、 2 2023/03/15 23:50
- PHP PHPでCSVを出力するさいに、ループの中で前の行の値を変更したい 1 2022/10/27 14:21
- PHP PHPでCSVを出力するさいに、ループの中で前の行の値を変更したい 3 2022/10/27 17:44
- C言語・C++・C# C言語初心者 構造体 課題について 2 2023/03/10 19:48
- PHP ファイルの書き込みについて教えて下さい。 1 2023/03/20 12:01
- C言語・C++・C# sprintf()の使い方について 1 2022/08/17 16:16
- C言語・C++・C# このプログラミングの問題を教えて欲しいです。 キーボードから整数kを入力し、kが配列aの中に何個存在 2 2022/12/19 22:50
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
VBAの配列サイズとメモリに関して
-
C言語で、メモリを解放しないで...
-
メモリのセグメント違反の解決...
-
LoadLibraryしたらFreeLibrary
-
メモリの解放について VB6 VBA
-
C言語における再帰呼び出しの...
-
メモリ不足
-
動的メモリとexit(C言語)
-
【C言語】再帰が時間がかかる...
-
C#のOutOfMemoryException発生...
-
ファイルマッピング関数で失敗
-
メモリアロケーション異常の発...
-
再帰関数について
-
Bitmapを重ね合わせる方法
-
EXCEL-VBAにてADOのレコードセ...
-
プログラムの最大メモリ消費量...
-
緯度、経度の 10進法と 60進法...
-
Macターミナルで実行中のプログ...
-
スレッドの安全な終了のさせ方
-
バックグラウンドのプロセスの...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C言語で、メモリを解放しないで...
-
VBAの配列サイズとメモリに関して
-
「ヒープサイズの設定」て何?
-
C言語における再帰呼び出しの...
-
エクセルVBA 大容量CSVファイル...
-
動的メモリとexit(C言語)
-
エクセルのメモリ使用状況/Appl...
-
メモリが不足しています(VBA)
-
ファイルマッピング関数で失敗
-
大容量のメモリ確保をスワップ...
-
メモリのセグメント違反の解決...
-
メモリ不足
-
EXCEL-VBAにてADOのレコードセ...
-
エクセル キャッシュメモリー...
-
【C言語】再帰が時間がかかる...
-
C#のOutOfMemoryException発生...
-
メモリの解放について VB6 VBA
-
バッチファイルでの実行EXEのメ...
-
closeとメモリの開放について
-
「memcpy」と「strcpy」について
おすすめ情報