スタックオーバーフロー – 固定ページ 2 – プログラミング – Home

スタックオーバーフロー
 
通知
すべてクリア

[解決済] スタックオーバーフロー

固定ページ 2 / 2

PATIO
(@patio)
Famed Member
結合: 3年前
投稿: 2660
 

すいません、完全に錯綜してますね。


返信引用
PATIO
(@patio)
Famed Member
結合: 3年前
投稿: 2660
 

思うんですが、3000個のデータを登録するのに毎回一次オブジェクトを
生成するのは無駄なような気がします。
ローカルを一つ作っておいて、それに設定してはmapに追加では駄目なんでしょうか。
その方が早いような気がしますけれど。


返信引用
PATIO
(@patio)
Famed Member
結合: 3年前
投稿: 2660
 

基、一時オブジェクトですね。


返信引用
仲澤@失業者
(@uncle_kei)
Prominent Member
結合: 5年前
投稿: 828
 

そうなると、単純な理由ではありませんね。

ためしに、3000個の生成をforでまわしてみてはどうでしょう。
全て同じ引数でかまいません。これでもオーバーするようだと、
疑わしいのはCHogeのコンストラクタ、またはその引数となって
いるもののコンストラクタのどれかぢゃないでしょうか。

VS2003ですが、32byteの構造体で3万個程度はぜんぜんOKでした。


返信引用
ロマ
 ロマ
(@ロマ)
ゲスト
結合: 18年前
投稿: 170
 

マクロを展開して、
result.insert(std::make_pair(0, CHoge(aaa, 1, 9, 2, ...); //A
result.insert(std::makke_pair(, CHoge(bbb, 2, 9, 4, ...); //B

コンパイラの癖やオプションの設定で異なるかもしれませんが、
BのCHogeはAのCHogeとは別のメモリー上に作られているようです。

get_hoge()は、最初に、
スタック上にsizeof(CHoge)*3000のメモリーを確保しようとして、
失敗しているのだと想像します。

詳しくはアセンブラー出力を眺めてください。

私なら、const CHoge[] = { CHoge(aaa,..), ...};を作ります。
コンパイル時にconst mapを作ってしまう方法は分かりません。識者殿よろしく。


返信引用
仲澤@失業者
(@uncle_kei)
Prominent Member
結合: 5年前
投稿: 828
 

「ウオッチ」で@ESP を監視するのでもよいかも。


返信引用
vine
 vine
(@vine)
ゲスト
結合: 14年前
投稿: 9
Topic starter  

>>PATIO

>思うんですが、3000個のデータを登録するのに毎回一次オブジェクトを
>生成するのは無駄なような気がします。
>ローカルを一つ作っておいて、それに設定してはmapに追加では駄目なんでしょうか。
>その方が早いような気がしますけれど。

これ、ためしにやってみましたが、ダメでした。というか、だいぶコードを削っても、
同じようにスタックオーバーフローでした。

void get_hoge(void)
{
#define ADD_HOGE(idx, a, b, c, d, ... ) \
{ \
CHoge(a, b, c, d, ...))); \
}
 
ADD_HOGE(0, aaa, 1, 9, 2, ...)
ADD_HOGE(1, bbb, 2, 9, 4, ...)
ADD_HOGE(2, ccc, 3, 9, 2, ...)
// 以下3000行程度、ADD_HOGEマクロを使用
}

上のコードは、単にCHogeのコンストラクタとデストラクタを3000回程度コール
するコードとなります。やはり3000行の部分を大幅にカットしないと、スタック
オーバーフローとなります。

ちなみに、3000行の部分を大幅にカットして実行し、デバッガにてデストラクタが
コールされることを確認しました(スタックは関係ないですけど)。


返信引用
ロマ
 ロマ
(@ロマ)
ゲスト
結合: 18年前
投稿: 170
 

まちがった。
> 私なら、const CHoge[] = { CHoge(aaa,..), ...};を作ります。
const CHoge array[]でござる。
関数内なら、static constね。


返信引用
vine
 vine
(@vine)
ゲスト
結合: 14年前
投稿: 9
Topic starter  

>ロマ
返信ありがとうございます。

(ここからVS2008で試しました)

おっしゃる通りでした。右辺値に対するポインタを取得して表示させてみたら、
確かに異なっていました。debug でも release でもです。正直驚きました。
(要 #pragma warning(disable: 4238) )

ちなみに、

CHoge* ptr;

#define ADD_HOGE \
{ \
ptr = &CHoge(", ", 0, 0, 0, ...); \
printf(%d , ptr); \
}

CHoge の引数の数は60個です(先頭2個はstd::string、残りはint)。

release にて、ADD_HOGE を60回コールしたら、最初の59個は同じ値となりました。
60回以下でも似たようなものです。
しかし、70回コールしたら、完全にバラバラな値となりました。

この辺、コンパイラの癖、最適化もしくはその他の事情がありそうですね。

とにかく、一時変数が「一時的ではない」スタックの過度な消費に繋がる可能性が
あることを肝に銘じておきます。

返信してくれたみなさん、ありがとうございました。


返信引用
PATIO
(@patio)
Famed Member
結合: 3年前
投稿: 2660
 

えっと、たぶん試されたのは私が言っている方法とは違うと思います。

私が言いたいのは、

CHogeにメンバーを一気にセットするSetメソッドを作成しておいて

ロカールに
CHoge work(", ", 0, 0, 0, ...);

と作成しておき、

work.Set(aaa, 1, 9, 2, ...);
としてから
result.insert(std::make_pair(0, work));
とすればいいんではという意味です。

こうするとローカルには一つしか生成されないはず。

あとはwork.Setとresult.insertの繰り返しになるので
CHogeのオブジェクトの生成はおこらないと思います。

スコープと寿命のところでも書いていますが、
スコープと寿命が必ずしも一致しないなら
マクロでやっている限り、呼び出した数だけ変数ができると思います。


返信引用
固定ページ 2 / 2

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました