VC++6.0 ダイアログベース WindowsXPです。
以下の構造体配列を宣言し、実行すると
死にます。
これはサイズが大きすぎるからなのでしょうか?
PCのメモリは512Mです。
#define MAX_LOG_DATA_NUM 27593 // 最大LOGデータ数
#define MAX_LOG_DATA_LEN 0x64 // 最大LOGデータ長
typedef struct{
short year;
char month;
char day;
char hour;
char min;
char sec;
short ms;
} TIME_INFO;
// LOG情報構造体
typedef struct{
TIME_INFO time; // 日時時間
char code; // 識別コード
char data[MAX_LOG_DATA_LEN]; // LOG情報
} LOG_INFO;
LOG_INFO m_FileLog[MAX_LOG_DATA_NUM]; //## ←こいつです。
変数名がm_で始まっていることから、クラスのメンバ変数だと仮定すると、
そのクラスのサイズが3Mバイト以上になります。
また、スタックサイズのデフォルト値は 1Mバイトですので、
そのクラスのインスタンスをローカル変数とするなどで、スタック上に作成すると、
確実にスタックオーバーフローします。
クラスのインスタンスをヒープから確保するか、
このメンバ変数を動的確保で保持するようにしましょう。
> これはサイズが大きすぎるからなのでしょうか?
十中八九そうですね。
PCのメモリ以前に、スレッド内で使える「スタックサイズ」が、
VC6のデフォルトでは1MBしかありません。(他のデータなども合わせて、1MB)
上記を自動変数で確保しているなら「スタックオーバフロー」します。
new 等で動的に確保してみてください。
> 以下の構造体配列を宣言し、実行すると
> 死にます。
コンパイルはできているんですね?
じゃあ現象は違うと思うのですが、私の環境ではコンパイルもできませんでした。
原因はdefineの数字の後の全角スペースでした。
REEさん、ありがとうございます。
クラスのメンバ変数です。
3M以上はダメなのですね?初めて知りました。
ちなみにデバッグモードで実行すると、スタックオーバーフローとエラーがでました。
1.このクラスのcppファイルの先頭でグローバル宣言すれば大丈夫ですよね!?
2.new演算子を使って動的にこのクラスのヘッダファイル内でメンバ変数として宣言し
ても平気なのですか?そうするとこのクラスのメンバ変数として扱えるようになる
がメモリはヒープエリアから用いているということになりますかね?
ちなみに、ヒープエリアのサイズ制限はあるのですか?
>3M以上はダメなのですね?初めて知りました。
3M以上と書いたのは、そのデータがそれくらいの大きさという意味で、
理由からも分かるとおり、デフォルトでは、1M以上でだめです。
(実際にはスタックは他の用途にも使われるので、1M未満でも1Mに近いとだめです。)
>1.このクラスのcppファイルの先頭でグローバル宣言すれば大丈夫ですよね!?
大丈夫ですが、グローバルにするくらいなら、
staticメンバ変数にした方がいいかもしれません。
>2.new演算子を使って動的にこのクラスのヘッダファイル内でメンバ変数として宣言し
> ても平気なのですか?そうするとこのクラスのメンバ変数として扱えるようになる
>がメモリはヒープエリアから用いているということになりますかね?
メンバ変数の宣言と同時にnew演算子で初期化しようとしているなら無理です。
普通は、配列の変わりにポインタで宣言し、
コンストラクタなどで、new演算子で確保します。(もちろんデストラクタで解放)
また、本題からは外れますが、常に最大のサイズが必要ということでなければ、
可変配列(CArray,std::vector)や文字列クラス(CString,std::string)などを使うのも手
です。
>ちなみに、ヒープエリアのサイズ制限はあるのですか?
無限に取れるわけはないので、もちろんありますが、ギガバイト単位の話です。
REEさん、色々ありがとうございます。勉強になります。
クラスのメンバ変数というのは、スタック領域に割り当てられるのですね?
>staticメンバ変数にした方がいいかもしれません。
これで宣言するとスタックオーバーフローにはならないのですか?
ちなみに、static演算子については、使ったことがないわけではないのですが(VCでは
ない)、ほとんど使い方をしりません。どういうとき使ったらいいのかわかりません。
グローバル変数との違いがよくわかりません。
> クラスのメンバ変数というのは、スタック領域に割り当てられるのですね?
違います。
クラスのインスタンスがスタック領域に確保された場合は、当然そのメンバ変数もスタックに割
り当てられます。
クラスのインスタンスをヒープ領域に確保すれば、メンバ変数は当然ヒープ領域になります。
staticにすると、スタックとは別領域(グローバルと同じような領域)に確保されます。
> ちなみに、static演算子については、
> (省略)
> グローバル変数との違いがよくわかりません。
とりあえず、staticとグローバルではスコープが異なります。
グローバルはどこからでもアクセスできますが、
staticなオブジェクトは、翻訳単位外から直接アクセスすることができません。
>クラスのインスタンスがスタック領域に確保された場合
これは、ようするにローカルで別クラスの宣言をした時とかですかね?
まず、staticとグローバルは相反するものではありません。
グローバルかどうかは宣言・定義の位置で決まります。
staticはそれに対する修飾です。
とりあえず、変数の種類とスコープと一般的な記憶域です。
・staticグローバル変数・・・翻訳単位からアクセス可能・・・静的記憶領域
・非staticグローバル変数・・・どこからでもアクセス可能・・・静的記憶領域
・staticメンバ変数・・・publicならどこからでもアクセス可能・・・静的記憶領域
・非staticメンバ変数・・・publicならどこからでもアクセス可能・・・それをメンバに
持つクラス,構造体と同じ領域
・staticローカル変数・・・関数内でアクセス可能・・・静的記憶領域
・非staticローカル変数・・・関数内でアクセス可能・・・スタック
>>クラスのインスタンスがスタック領域に確保された場合
>これは、ようするにローカルで別クラスの宣言をした時とかですかね?
そうです。(厳密には宣言ではなく定義)
>グローバルかどうかは宣言・定義の位置で決まります。
>staticはそれに対する修飾です。
これはわかってます。よくわからないのは使い方です。
Cでも同じだと思いますが、【staticグローバル変数】はどういう時に使いますか?グロ
ーバルの場合、staticにする意味があるとは思えないのですが・・・
>翻訳単位
これはどういう意味ですか?
1.1M以上の【非staticメンバ変数】を宣言して実行するとなぜオーバーフローするの
でしょうか?
スタック領域に割り振られないのなら平気なのでは?
2.クラスAで【protected】でメンバ変数を定義したものは、
クラスBでクラスAのインスタンスを定義してもアクセスできないですよね?(public
だけアクセス可能)
クラスA内の変数、関数に他クラスからまったくアクセスしない場合は、
public、prootectedの区別をつける意味はないという認識でいいでしょうか?
まとめると、意味はおよそ理解してるが、prootectedで定義したほうがよいというよう
な状況がわからないのでpublicでしか定義したことがないのです。
REEさんはどういう時に使い分けますか?
>>翻訳単位
>これはどういう意味ですか?
簡単に言うと、一つの拡張子がc(又はcpp)のファイルです。
>1.1M以上の【非staticメンバ変数】を宣言して実行するとなぜオーバーフローするの
でしょうか?
>スタック領域に割り振られないのなら平気なのでは?
・非staticメンバ変数・・・それをメンバに
持つクラス,構造体と同じ領域
・非staticローカル変数・・・スタック
それをもつクラスが非staticローカル変数として作成されるとスタック領域に割り振られ
ます。
>2
>関数に他クラスからまったくアクセスしない場合
間違って参照したときにエラーになるように
出来るだけprotected又は、privateにします。
そのための指定です。
>REEさんはどういう時に使い分けますか?
必然性が無い時は、指名して質問しないようにしましょう。
必然性がある場合:他の人の回答では意味がない場合
>必然性が無い時は、指名して質問しないようにしましょう。
ごもっともです。失礼しました。
>非staticローカル変数・・・スタック
>それをもつクラスが非staticローカル変数として作成されるとスタック領域に割り振
>られます。
これはもちろんわかります。
でも今回の場合、【非staticメンバ変数】なのですが・・・
>間違って参照したときにエラーになるように
>出来るだけprotected又は、privateにします。
なるほど。基本はprivateで定義して、もし他クラスからアクセスするような状況になっ
た物だけpublicに変更する。って感じでコーティングを進めたほうがよいということで
すね。
> でも今回の場合、【非staticメンバ変数】なのですが・・・
ということは当然、そのクラス自体がスタック上に確保されると、
メンバ変数の方もスタックに確保され、そこでオーバフローしますね。
> それをメンバに持つクラス,構造体と同じ領域
# > なるほど。基本はprivateで定義して、もし他クラスからアクセスするような状況になっ
# > た物だけpublicに変更する。って感じでコーティングを進めたほうがよいということですね。
# 一つの考え方として間違ってはいない気もしますが、コーディング中にそうころころと
# 変わるものではないと思います。最初から public にしておいた方がいいものもあるので。
# 「オブジェクト指向」とか「カプセル化」、「隠蔽」とか調べてみるとよいかと。