すみません。一度質問を載せた後で、補足で絵を載せようとしたのですができなかったので
再投稿させていただきます。(元の質問はけしました。)
--------------------------------------
こんにちは、今作成しているエクセルの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.3
- 回答日時:
単にOSのキャッシュが効いてるだけでは。
BSTRキャッシュを無効にしてみるとか。
※ BSTR(VBAのString型の事)
この回答への補足
BSTRキャッシュを無効というのは、String型以外にしろということでしょうか?
残念ながら、扱う値は文字列なのです。
確かに、long型とかだと、値変えてもあまり変化ないですね。
string型だと可変長の長さを持っている為、
一度大きな文字列を入れてしまうと、文字列を後から入れなおしても
メモリの番地を詰めることができないということなんでしょうか・・・
文字列だと不可能なんですかね
No.4
- 回答日時:
>そうですか、では、配列の上限値をもとの状態に戻すことは不可能なのでしょうか?
申し訳ありませんが可能かどうか私にはわかりません。
#2の方がいわれるように断片化が原因であるなら再起動するしか手はないと思いますが。
この回答への補足
なるほど、断片化が原因なら無理なんですね。
どうも、それっぽい感じもしますね。
NO2でちょっと勝手ながら断片化の解釈しちゃってますけど
あれだと、配列が同じ数だけしか作れない事の
つじつまがあいますし、Excelの再起動で直るわけですし。
そうなると、なるべく配列は減らして、影響を少なくなるように設計するしかなさそうですねぇ・・・
毎回マクロ実行するたびにexcel起動しなおさなければならないのもあれですが・・・
No.5
- 回答日時:
> BSTRキャッシュを無効というのは、String型以外にしろということでしょうか?
(用語の意味が分からないなら)ググらないと。
参考URL:http://keicode.com/com/bstr-cache.php
この回答への補足
すみません。ご親切にありがとうございます。
システム環境変数にOANOCACHE=1を追加して、PCを再起動してみましたが、特に変化は見られませんでした。
やはり、無理なのでしょうか
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Visual Basic(VBA) VBA横データを縦にしたいです 2 2023/08/08 19:38
- Visual Basic(VBA) ファイル全てを .xlsm に変更したところ、プログラムが途中で落ちてしまっています 17 2022/12/07 12:03
- Visual Basic(VBA) 改行ごとに行を追加し、数量を分割 4 2023/07/11 16:39
- Visual Basic(VBA) 複数シートの複数列に入力されているデータを重複なしで抽出するVBAを作りたいです。 9 2022/06/17 10:33
- Excel(エクセル) VBAで組み合わせ算出やCOUNTIFSの処理を高速化したいです。 4 2022/04/07 02:38
- Visual Basic(VBA) VBAでのMATCH関数 3 2022/10/17 19:06
- Visual Basic(VBA) マクロVBA 1シートをまとめる 閉じ方 初心者 SOS! 1 2022/06/17 14:54
- Visual Basic(VBA) コード名シートA列と集計シートA列のコードが一致したら、コード名シートA5からk12の範囲をコピーし 1 2022/08/29 23:46
- Visual Basic(VBA) 別シートから年齢別の件数をカウントしたいの続き 5 2023/01/24 00:16
- Perl perl このテキストファイルを簡単に配列に入れるには? 2 2022/04/27 20:24
このQ&Aを見た人はこんなQ&Aも見ています
-
プロが教える店舗&オフィスのセキュリティ対策術
中・小規模の店舗やオフィスのセキュリティセキュリティ対策について、プロにどう対策すべきか 何を注意すべきかを教えていただきました!
-
Redimした動的配列はEraseする必要があるのか
Visual Basic(VBA)
-
VBAの配列サイズとメモリに関して
Visual Basic(VBA)
-
EXCELのVBAで作業ファイルを閉じてもメモリの解放をしなくて困っています
Excel(エクセル)
-
-
4
ExcelのVBAでメモリ解放できない
Visual Basic(VBA)
-
5
EXCEL VBA マクロ 実行する度に処理速度がどんどん遅くなる原因が知りたい
Excel(エクセル)
-
6
DoEventsが必要な理由について
Visual Basic(VBA)
-
7
VBA public変数はどのようなことをしたら解放されますか?
Visual Basic(VBA)
-
8
EXCEL VBAで全選択範囲の解除
Excel(エクセル)
-
9
WorkBooksをオープンさせずにシートにコピーしたい【EXCEL VBA】
Excel(エクセル)
-
10
Redim とEraseの違いは?
Access(アクセス)
-
11
VBA:結合されたセルに対する「Target」について
Access(アクセス)
-
12
メモリの消費量について
Visual Basic(VBA)
-
13
ExcelVBA実行後に時々落ちる
Visual Basic(VBA)
-
14
エクセルVBA Unionはなぜ遅い?
Visual Basic(VBA)
-
15
VBAでの[]
Visual Basic(VBA)
-
16
エクセルVBA 配列からセルに「関数式」を一気代入したい
Visual Basic(VBA)
-
17
VBA ReDim と ReDim Preserve の速度差
Visual Basic(VBA)
-
18
VBA 1次元配列を2次元に追加する
Visual Basic(VBA)
-
19
エクセルのメモリ使用状況/Application.Memoryの代替手段
Visual Basic(VBA)
-
20
別ブックからユーザーフォームを実行したい~!!
Visual Basic(VBA)
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
配列を使わずに、変数名を動的...
-
2次元配列を戻り値とする関数?
-
先頭アドレスとは何ですか?
-
C言語 配列の長さの上限
-
ExcelVBAで質問です。離れた二...
-
C# 配列の変数宣言について。
-
C# Listを使わずに2次元配列の...
-
unsigned char配列への入力の仕方
-
配列で格納したものをmsgboxで...
-
構造体配列を引数とするDLL作成...
-
Excel、VBAのユーザーフォーム...
-
Redimした動的配列はEraseする...
-
C言語初心者 ポインタについて...
-
VBで構造体の配列を関数に渡す...
-
テキストファイルから文字列を...
-
C言語 配列の再初期化
-
C言語でcharの足し算
-
配列の参照渡しで型が一致しま...
-
なぜ配列は0から始まるのです...
-
VB.NET 構造体の配列の検索機能...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C言語 配列の長さの上限
-
配列を使わずに、変数名を動的...
-
配列で格納したものをmsgboxで...
-
配列の参照渡しで型が一致しま...
-
C# Listを使わずに2次元配列の...
-
VBで構造体の配列を関数に渡す...
-
複数の選択範囲の行番号を個別...
-
パイソンの
-
先頭アドレスとは何ですか?
-
【速いブラインドタッチ】手を...
-
C# 配列の変数宣言について。
-
C言語初心者 ポインタについて...
-
unsigned char配列への入力の仕方
-
テキストファイルから文字列を...
-
ExcelVBAで質問です。離れた二...
-
Redimした動的配列はEraseする...
-
C言語で特定列だけを抽出して配...
-
擬似コード 長さがmの配列でな...
-
メモリの初期値
-
C言語初心者 構造体 課題について
おすすめ情報