すみません。一度質問を載せた後で、補足で絵を載せようとしたのですができなかったので
再投稿させていただきます。(元の質問はけしました。)
--------------------------------------
こんにちは、今作成しているエクセルのVBAで配列を膨大に食ってしまい、メモリ不足に落ちいるという現象に悩まされています。
そのため、なるべくいらなくなった配列はEraseステートメントを使って解放しようとしてるのですが、
これが上手くいっている気がしません。
ためしにフォームと、ラベルを1つずつ用意し、下記のような配列をどこまで作れるか計算するプログラムを組んでみました。
1回目、ans(i) に"a"というaを1個のみ格納した場合で計算すると、配列は2970万個できます。
2回目、ans(i) に"aaa~a"というaを64個格納した場合で計算すると、配列は770万個できます。
まぁ、ここまでは当然の結果だと思います。
可変長のString型変数の場合は、割り当てられるメモリサイズが固定ではないらしいので
(前回の質問で教えてもらいました)
しかし3回目、ここでもう一回、1回目と同じ、"a"を一個のみ格納した場合で計算してみます。
私の予想では1回目と同じ2970万個程度の配列が作れると思っていました。
なぜなら、Eraseステートメントでメモリを解放していたし、
タスクマネージャーのPF使用量(おそらくメモリの値)を見ても2回目を実行した後の値は
1回目前と同じ値に戻っているからです。
しかし、実際試してみると、
2回目と同じ770万個の配列しかつくれませんでした。
つまり、Eraseステートメントを使用しても配列の上限値は元の状態に戻らなかったのです。
どうすれば、配列を再び2970万個作れる初期の状態に戻せるのでしょうか?
現時点ではエクセルを起動しなおせば、元に戻りますが、それでは困ります
(プログラムの途中で配列の数を減らしたり、コピーしたりを行っている為、
どうしてもプログラム中でメモリの解放を行いたいからです)
また、添付した絵は、実行した時のタスクマネージャーの様子です。
参考になれば幸いです
どうか、みなさんお知恵をお貸ししてください
---------------------------------------------------
'実行するときは、フォームとラベルを1つずつ用意して実行してください
Public Sub 配列上限取得計算()
On Error GoTo ErrEnd
Dim i As Long
Const kankaku As Long = 100000
Dim ans() As String
ReDim ans(1 To kankaku) As String
ans(1) = 1
i = 2
UserForm1.Show vbModeless
Do
If i Mod kankaku = 0 Then
DoEvents
UserForm1.Label1 = i
ReDim Preserve ans(1 To i + kankaku) As String
End If
'最初にaを1個のみ格納した場合は、2970万個まで配列が作れるが、次にaを64個格納した場合は770万個まで作れた。
'しかし、その直後にまた、aを1個のみ格納した場合で実行してみると、770万個しか作れない
'つまり、Eraseステートメントを使っているにも関わらず、同じ条件のプログラムでも配列の上限が下がってしまう。
'この現象をなんとか回避したい。元の状態にリセットするにはエクセルを起動しなおさないと直らない。
'1回目と3回目に実行するコード、2回目はコメントアウトしてください
ans(i) = "a"
'2回目に実行したコード、2回目はコメントアウトを解除してください。
' ans(i) = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
i = i + 1
Loop
Erase ans
Unload UserForm1
Exit Sub
ErrEnd:
Erase ans
MsgBox "これ以上の配列を設定できません。" & vbCrLf & "上限は" & i & "です。" & vbCrLf & Err.Description
Unload UserForm1
End Sub
No.2ベストアンサー
- 回答日時:
使用メモリが断片化して、2970万個分の連続領域が確保できない、というケースもありそうです。
初期化ですが、Excel再起動以外の方法は、私は知りません。
この回答への補足
そうですか・・・断片化と聞いて勝手に想像してみたのですが
"a"がアドレス一個分のメモリを消費
"aaaaaaa~a"がアドレス100個分のメモリを消費すると仮定した場合
最初に
a(0):001番地
a(1):002番地
a(2):003番地
といった具合だったのが
a(0):001~100番値
a(1):101~200番値
a(2):201~300番値
といった感じで、メモリのアドレスを占有するけれど
次に、"a"で格納しようとした場合、実際に使うのは1個分のアドレスだけど
a(0):001番値、002~100番地はデータのゴミ
a(1):101番値、102~200番地はデータのゴミ
a(2):201番値、202~300番地はデータのゴミ
という感じになって、002~100番地を有効に使えないようなイメージでしょうか。
どうにか解決策が知りたいです。
No.5
- 回答日時:
> BSTRキャッシュを無効というのは、String型以外にしろということでしょうか?
(用語の意味が分からないなら)ググらないと。
参考URL:http://keicode.com/com/bstr-cache.php
この回答への補足
すみません。ご親切にありがとうございます。
システム環境変数にOANOCACHE=1を追加して、PCを再起動してみましたが、特に変化は見られませんでした。
やはり、無理なのでしょうか
No.4
- 回答日時:
>そうですか、では、配列の上限値をもとの状態に戻すことは不可能なのでしょうか?
申し訳ありませんが可能かどうか私にはわかりません。
#2の方がいわれるように断片化が原因であるなら再起動するしか手はないと思いますが。
この回答への補足
なるほど、断片化が原因なら無理なんですね。
どうも、それっぽい感じもしますね。
NO2でちょっと勝手ながら断片化の解釈しちゃってますけど
あれだと、配列が同じ数だけしか作れない事の
つじつまがあいますし、Excelの再起動で直るわけですし。
そうなると、なるべく配列は減らして、影響を少なくなるように設計するしかなさそうですねぇ・・・
毎回マクロ実行するたびにexcel起動しなおさなければならないのもあれですが・・・
No.3
- 回答日時:
単にOSのキャッシュが効いてるだけでは。
BSTRキャッシュを無効にしてみるとか。
※ BSTR(VBAのString型の事)
この回答への補足
BSTRキャッシュを無効というのは、String型以外にしろということでしょうか?
残念ながら、扱う値は文字列なのです。
確かに、long型とかだと、値変えてもあまり変化ないですね。
string型だと可変長の長さを持っている為、
一度大きな文字列を入れてしまうと、文字列を後から入れなおしても
メモリの番地を詰めることができないということなんでしょうか・・・
文字列だと不可能なんですかね
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
このQ&Aを見た人はこんなQ&Aも見ています
-
準・究極の選択
「年収1000万円で一生カレーライス」か 「年収180万円で毎日何でも食べ放題」 あなたはどちらを選びますか?
-
フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
あなたが普段思っている「これまだ誰も言ってなかったけど共感されるだろうな」というあるあるを教えてください
-
映画のエンドロール観る派?観ない派?
映画が終わった後、すぐに席を立って帰る方もちらほら見かけます。皆さんはエンドロールの最後まで観ていきますか?
-
海外旅行から帰ってきたら、まず何を食べる?
帰国して1番食べたくなるもの、食べたくなるだろうなと思うもの、皆さんはありますか?
-
天使と悪魔選手権
悪魔がこんなささやきをしていたら、天使のあなたはなんと言って止めますか?
-
VBAの配列サイズとメモリに関して
Visual Basic(VBA)
-
Redimした動的配列はEraseする必要があるのか
Visual Basic(VBA)
-
EXCEL VBA マクロ 実行する度に処理速度がどんどん遅くなる原因が知りたい
Excel(エクセル)
-
-
4
EXCELのVBAで作業ファイルを閉じてもメモリの解放をしなくて困っています
Excel(エクセル)
-
5
Redim とEraseの違いは?
Access(アクセス)
-
6
Excelのセルの色指定をVBAから配列を用いて効率的に行う方法はあり
Visual Basic(VBA)
-
7
DoEventsが必要な理由について
Visual Basic(VBA)
-
8
配列でデータが入っている要素を求める方法
Visual Basic(VBA)
-
9
エクセルVBA Unionはなぜ遅い?
Visual Basic(VBA)
-
10
VBA public変数はどのようなことをしたら解放されますか?
Visual Basic(VBA)
-
11
vbaのエラー対応(実行時エラー7:メモリが不足しています)
Visual Basic(VBA)
-
12
コマンドプロンプトの「%1」と「%~1」の違いがわからない
その他(プログラミング・Web制作)
-
13
メモリが不足しています(VBA)
Visual Basic(VBA)
-
14
全ての変数を一気にリセットする方法はありますか?
PowerPoint(パワーポイント)
-
15
Excelのメモリ(配列)の上限は2Gではないのか
Excel(エクセル)
-
16
ExcelのVBAでメモリ解放できない
Visual Basic(VBA)
-
17
VBAでブックを非表示で開いて処理して閉じる方法
Excel(エクセル)
-
18
Excel VBA 処理後データが重たくなる&処理スピードが遅いのを解決したい
Visual Basic(VBA)
-
19
VBA 変数名に変数を使用したい。
Visual Basic(VBA)
-
20
vba メモリーリーク
Visual Basic(VBA)
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・人生のプチ美学を教えてください!!
- ・10秒目をつむったら…
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・【大喜利】【投稿~9/18】 おとぎ話『桃太郎』の知られざるエピソード
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C言語 配列の長さの上限
-
配列を使わずに、変数名を動的...
-
C# 配列の変数宣言について。
-
配列で格納したものをmsgboxで...
-
C# Listを使わずに2次元配列の...
-
複数の選択範囲の行番号を個別...
-
C言語初心者 ポインタについて...
-
配列をEraseしてもメモリが開放...
-
なぜ配列は0から始まるのです...
-
先頭アドレスとは何ですか?
-
C++ 配列を返すには?
-
CSVファイルのデータを2次元配...
-
市販のビンゴカードについて
-
Excel、VBAのユーザーフォーム...
-
【C言語】配列の中に配列を入れ...
-
unsigned char配列への入力の仕方
-
エラ-メッセ-ジの意味を教え...
-
MFC、ダイアログベースでのモー...
-
ポインタの配列のコンマについて
-
メモリと配列に関して
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C言語 配列の長さの上限
-
配列を使わずに、変数名を動的...
-
配列で格納したものをmsgboxで...
-
C# Listを使わずに2次元配列の...
-
C# 配列の変数宣言について。
-
先頭アドレスとは何ですか?
-
C言語で特定列だけを抽出して配...
-
配列の参照渡しで型が一致しま...
-
VBで構造体の配列を関数に渡す...
-
C++ vectorに配列をプッシュしたい
-
【速いブラインドタッチ】手を...
-
unsigned char配列への入力の仕方
-
配列をEraseしてもメモリが開放...
-
【C言語】配列の中に配列を入れ...
-
ExcelVBAで質問です。離れた二...
-
4勤2休のシフト作成
-
Functionの戻り値を2次元配列...
-
Redimした動的配列はEraseする...
-
配列を含む構造体の初期値について
-
複数の選択範囲の行番号を個別...
おすすめ情報