• 締切済み

ASPのReDim Preserveについて

いつもお世話になります。 ASP(VBScript)で教えて頂きたいことがあります。 VBScriptにはJavaでいうArrayListのようなコレクション機能がないので、動的配列を実現するためには ReDim PreserveやScripting.Dictionaryを使用しなければなりませんよね。 そこで、DBから取得したレコードを、ループする度毎にReDim Preserveを使用し、データをセットするよう な実装をしていました。すると、ReDim Preserveは問題があるのでやめた方がよい、と言われました。 具体的には、ReDim Preserveをすることによって、新たに配列を作成し、古い内容をコピーするため、 倍々にメモリを食いつぶしていくことになり、それが大きくなるとどんどん遅くなっていき、そしてメモリリーク になる、ということでした。 自分なりに調べてみたのですが、そのような記事を見つけることができませんでしたし、JavaのArrayList でも内部的には配列を持っており、配列の再作成などをやっています。 ○○百万件などといった大量件数を扱う際は、それはメモリリークにならないような設計、実装をしなければ ならないとは思うのですが、それはどの言語でも共通で言えることであって、特別にVBScriptではやめた方がよい、 とは思えません。 ReDim Preserveを使用しても、先に述べたような認識をもっていれば問題ないと思うのですが、どうでしょうか。 VBScriptは、こういう仕組みだから駄目なんだ、という理由があるのでしょうか。もしあれば、根拠となる サイトなど教えて頂けると嬉しいのですが。。。 宜しくお願い致します。

みんなの回答

  • shockatz
  • ベストアンサー率80% (153/191)
回答No.1

VBScriptのReDim Preserve(懐かしい)に限らず、静的配列の確保というのは、非常にコストのかかる処理で、それをループで連続実行することは何にせよ良くありません。 また、コレクション系の変数は、静的変数と違って、ポインタを用いた可変データストアが可能なため、アクセス速度やメモリ効率は劣るにせよ、データ量が可変する配列を収めるには必須のものだと思います。 JavaのArrayListが、内部的に静的配列で処理されているというのは初耳です。 そのようなことはあり得ないと思いますが、ご質問の趣旨からは外れますので、あえて突っ込みません。 「コレクションやジェネリックが完璧に使えるASP.NETでなく、何で今さらASP?」という素朴な疑問はありますが、どうしてもASP/VBScriptでReDim Preserveを使うのであれば、いったんDBから件数を取得して、その配列を確保してから処理を行うべきです。 また、Webでは大量の配列をハンドリングすることはなく、ページング処理でデータを部分取得しますが、そのような場合でも、ループ中で静的配列の確保をを繰り返してはいけません。

関連するQ&A

  • ReDim PreserveよりもReDimが遅い

    こんにちは、配列がいくつまで取得できるのか計算するマクロを作っている時に変なことに気が付きました。 エクセルでフォームとラベルを1つ用意し、下記のようなプログラムをモジュールに書きます。 実行すると、10万ずつ数字が増えていき、数字が1000~2000万超えたあたりで、メモリ不足ですという 表示がでます。 ここで、ReDim PreserveのPreserveをとって、ReDimだけにすると、数字の増え方が目に見えて遅くなります。 ReDim Preserveとしたときは9.5秒ぐらいですが ReDim の時は 30秒以上かかっています 3台のマシンでテストしましたが、どれも似たような結果になりました 普通に値を保持するredim Preserveの方が遅いと思うのですがなぜこのような結果になるのでしょうか? ご教授お願いいたします。 Public Sub 配列上限取得計算() On Error GoTo ErrEnd Dim i As Long Const kankaku As Long = 100000 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 'ここのPreserveをなくすと明らかに遅くなる ReDim Preserve ans(1 To i + kankaku) As String End If ans(i) = i i = i + 1 Loop Erase ans Unload UserForm1 Exit Sub ErrEnd: MsgBox "これ以上の配列を設定できません。" & vbCrLf & "上限は" & i & "です。" & vbCrLf & Err.Description Erase ans Unload UserForm1 End Sub

  • 動的配列確保

    JAVA初心者です。 VBでのRedim Preserve、CのreallocみたいなものはJAVAには無いのでしょうか? 要はあらかじめ配列数がわかっていない時に動的配列確保を行いたいのです。 Objectではなく、基本クラスのint、byte等の配列に使いたいと思っております。 ArrayListが近い事が出来そうだったのですが、Objectにしか使用出来ないので、 断念しました。教えてください。

    • ベストアンサー
    • Java
  • ReDim Preserveできなかった配列をUBOUND……

    VBScriptでプログラムを組んでおります。 初心者なので言葉の使い方が間違っているかもしれませんがご容赦ください。 ASPでDBにアクセスして、このときにReDim Preserveを使って配列(str)を動的に拡張しながらDBから項目を抽出しています。 この動的に作った配列の項目を表示する際にどうしても項目数が必要なので UBound(str)で要素数を抜き出して使用しています。 DBにデータがあれば問題ないのですが、DBにデータがない場合はUBound(str)実行時に -------------------------- Microsoft VBScript 実行時エラー (0x800A0009) インデックスが有効範囲にありません。: 'ubound' -------------------------- と表示されてしまいます。 これを回避するにはDBから1つの項目を抽出する度に+1するような変数を作れば事足りるとは思いますが、 そうすると配列内の項目を表示する関数の引数を増やすことになり、少し納得がいきません。 Dim str() において Redim str(1)をしたかしてないかを見分ける方法を教えてくださいませんか。 ……無ければ「無い」と仰ってくれれば助かります。 では失礼します。 お時間があればご協力宜しくお願いします。

  • [Fortran]VBでいうRedim Preserve

    元ネタ。 http://oshiete1.goo.ne.jp/qa4104356.html http://oshiete1.goo.ne.jp/qa4114624.html コンパイラ: G95 ソースファイル: http://cid-b89cb784f5346675.skydrive.live.com/self.aspx/TestCase/Q4114624/Q4114624-1.f95 ある程度Q4104356 #1を移植するつもりで書きました。 実際このソースコードをコンパイルし,6以上の偶数を二つの素数の和で出力できているのですが, VB6でいうReDim Preserveに相当するものをやろうとして ループ回数に応じて配列を広げるために allocateした配列をもう一度allocateしなおそうとするとエラーが出ます。そのため,無理やり要素数100000と固定した整数配列と,現在格納されている個数を持ち、使いまわすことで実装しています。 ReDim Preserve相当句 or std::vector<T>同等機能 or 変数のスコープをもっと狭くもてる実装方法 等、教えていただきたいと思ってます。 ========= 効率が悪いのは解ってますが,頭の中に入れて組み立てなおすのが面倒くさいのでAsanoNagiさんのアルゴリズムを使っていません。

  • Dictionaryについて3

    簡単に作ったソースなのですが、 以下の構文でエラーが発生します。 Dictionaryで作成したオブジェクトの束を配列として 格納させ、更にその配列を復帰値として取得し、メインルーチンにて展開させようと思っています。 以下のソースで考えられることございますか? 色々調べているのですが、述べ2日ハマっています。 ---------------------------------------------- Dim AAA,BBB(),CCC Set CCC=TEST 'CCCオブジェクトを展開し、値を画面に表示させる ’(未着手) private function TEST() Set AAA = CreateObject("Scripting.Dictionary") AAA.Add "1","111" ReDim Preserve BBB(0) Set BBB(0) = AAA Set TEST=BBB ←エラー個所 Exit Function End Function --------------------------------------------- エラー タイプ Microsoft VBScript 実行時エラー (0x800A01A8) オブジェクトがありません。

  • VBAで書き換え可能な可変配列を使用したいです。

    Collectionクラスを使った可変型の配列は要素の中身を書き換えることができず、一旦removeして同じキー名でaddしなくてはなりません。 VBAでJavaでいうArrayListのような可変かつ書き換え可能な配列を使う方法はないものでしょうか? どなたか教えて下さい。

  • VBScript で動的配列

    VBScript で動的配列 VB ではなく、VBScript で動的配列を実装したクラスはないでしょうか (自分で実装するのではなく、CreateObject() とかですぐにインスタンス化できるもの)。 私は C++ の STL で vector/list/map を多用していたのですが、VBScript で vector/list の様に使えるクラスを探しています (map は VBScript の Dictionary でだいたい似たようなことができる)。 条件としては、 (1) メモリの許す限り、要素をパカパカ追加していくことができる。 (2) 要素をすべて列挙できる。 (3) 要素を追加した順に列挙できる。 (4) 追加した順に要素を削除していくことができる (FIFO)。 (5) 追加した順とは逆順に要素を削除していくことができる (FILO)。 (6) 整数インデックスでランダムアクセスできる。 の様なものを探しています。(3)~(6) はオプションの条件なのですべて満たしている必要はありません。 「ReDim や Dictionary を使って自分で実装する必要がある」という意見の方は簡潔にそう記してください。実装方法は必要はありません。 なるべく、独自のクラスを定義することなく、そのまま使えるものがいいです。 ご存じの方、いましたら、よろしくお願いします。

  • VBAでバイナリとして配列の一部を書き込む方法

    配列a(256, 256)をまるごとバイナリデータとして書き込みたい場合には Put #1,,a a(256, 256)の配列に入った数値のうち、 a(51,51)~a(256,256) に入った数値のみをバイナリデータとして書き込みたいのですが どのようにすれば良いですか? で次元を変更して、この配列の中のデータを消さないままで a(0,0)~a(50,0)とa(0,0)~a(0,50) を削除してa(206,206)の配列を作成したいのですが、 ReDim Preserve a(206,206) とすると ”インデックスが有効範囲にありません”というエラーがでます。 http://hpcgi1.nifty.com/kenzo30/b_cbbs/cbbs.cgi?mode=al2&namber=7771&rev=&no=0&P=R&KLOG=51 このページにあるように、 ReDim Preserveは一次元配列でしか使えないそうです。 どうすれば一部だけバイナリに書き込めますでしょうか?

  • VBScriptで配列のソートをするには?

    VBScriptで作成した配列の順番をソートする場合、どのようなコーティングを行えば、実現できるでしょうか? ソートそのものを実装する関数がありますか?

  • VBAでオブジェクトの配列の配列の削除をすると動作異常になります

    VBA(Excel2000)でオブジェクト指向のお勉強をしておりますが、ミスか言語仕様か分からないトラブルがあり、困っております。 簡単な碁(碁盤を再現し、活き死に程度を判定する)のプログラムを作成していますが、クラス石の配列であるクラス群を作成し、更にクラス群の配列を石の黒・白別に標準モジュールで定義しています。一塊の石の群が死んでいると判定した時、その群を削除しようとするのですが、redim preserve 群の配列(添字-一番最後の)を実行すると、群の配列全体にアクセスできなくなってしまいます。redimする前に、Nothingを代入するとか、もとの群(石の配列)にNothingを代入してからredimするとかしてみましたが、事態は変わりませんでした。 仕様なのか、勘違いしているのか、クラスの使い方が分かっていないのか..アドバイスお願いします。

専門家に質問してみよう