ab.com コミュニティ

ActiveBasicを通したコミュニケーション
現在時刻 - 2024年4月28日(日) 01:47

全ての表示時間は UTC+09:00 です




返信する
ユーザー名:
件名:
メッセージ本文:
メッセージを入力してください。60000 字まで入力できます。 

フォントサイズ:
フォントカラー
オプション:
BBCode: ON
[img]: ON
[flash]: OFF
[url]: ON
スマイリー: OFF
BBCode を無効にする
URL を自動的にパースしない
クイズ
お手数ですがカタカナで「エービー」と4文字を入力してください。:
答えを正確に入力してください。答えられるかどうかでスパムボットか否かを判定します。
   

トピックのレビュー - メモリ解放時のエラー
作成者 メッセージ
  記事の件名:  わざわざどうもです。  引用付きで返信する
わざわざつくっていただいてすいません。
お手数お掛けしました。
ソースを(ざっと見て)比較してみたのですが
基本的には同じようです。
ほとんどがコピペのように一緒なのですが、
微妙に型が違っている部分が数箇所ありました。
そういえば作るときに勉強しながら大急ぎでつくったので
結構突貫工事だった気がします。
前回のミスといい、型が間違っていたようですね。(←もはや馬・・・)

それともう一点重要そうなのが、
いままでABのver3を使ったのですが、
konisiさんのソースをABver3で使うとエラーが沢山出ます。(これは当たり前として)
で、AB4用のものであると気づき実行してみると何の問題もなく出来ました。
連続演奏に対応するように書き換えたものも正常に動きました。
どうも旧バージョンに対する執着(?)が強かったのが原因のようです。
AB3でも型に気をつければ出来ると思ったのですが・・・。
ソースを手がかりに修正してみます。
わざわざありがとうございました。
投稿記事 Posted: 2008年8月10日(日) 13:22
  記事の件名:   引用付きで返信する
試しに適当に作ってみたのですが、特にエラーは出ないようです。
投稿記事 Posted: 2008年8月10日(日) 00:41
  記事の件名:  過去ログで気づいた  引用付きで返信する
過去ログに似たようなものを発見したのですが
引用:
> ヒープ領域に対してメモリを確保(HeapAlloc,HeapReAlloc)した場合、
> 実は確保したメモリ以上にデータを扱う事ができます。
> これは確保されたヒープハンドルがハンドルに過ぎないためであり、
> たまたま未確保の領域を侵しても実害が無かっただけに過ぎません。
>
> しかし、幾ら実害が無くても確保したヒープ領域を開放(HeapFree)すると、
> 確保した領域外のデータまでクリアしてしまうみたいで
> 初めてエラーが発覚したりします。
>
> この辺はABというよりAPIの問題になってきますので、
> 一度MSDN等を参照されることをお勧めします。
>
> http://www.microsoft.com/japan/msdn/
とまけイヌさんが書いていました。(そういえばこの名を聞くのも久しぶりダ・・・)
takさんが言っていることと本質的には変わりないのですが、
なんか結構面倒そうになってきた。
投稿記事 Posted: 2008年8月09日(土) 23:47
  記事の件名:  書き忘れ  引用付きで返信する
書き忘れましたが、
SRATE-1(もしくは確保領域を増やす)をするとエラー頻度は確実に減ります。
しかし100%ではありません。
というかムリだったらもうこれでもいいかな、なんて思ってきました。
投稿記事 Posted: 2008年8月09日(土) 23:19
  記事の件名:  すぐに出来るのでやってみましたが・・・  引用付きで返信する
ちょっとした改良なので即実行してみましたが
同様のエラーが出てしまいました。
似たような考えで確保する領域を増やす方法も考えたのですが
だめでした。
コード:
ZeroMemory(VarPtr(pwh),sizeof(WAVEHDR))
pwh.lpData=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,SRATE)'SRATEは曲の長さ
For i=0 TO SRATE-1
    pwh.lpData(i)=(i番目のデータ)←省略している
Next
pwh.dwBufferLength=SRATE
pwh.dwFlags=WHDR_BEGINLOOP or WHDR_ENDLOOP
pwh.dwLoops=1
waveOutPrepareHeader(hwo,pwh,sizeof(WAVEHDR))
waveOutWrite(hwo,pwh,sizeof(WAVEHDR))
それとやってて気づいたのですがwaveOutUnprepareHeaderのときにも
エラーが出るようです。こちらのエラーのほうが頻度が低いです。
コード:
Function MainWndProc(hWnd As DWord, dwMsg As DWord, wParam As DWord, lParam As DWord) As DWord
    ' TODO: この位置にウィンドウメッセージを処理するためのコードを記述します。
    Select Case dwMsg
      case MM_WOM_DONE
        waveOutUnprepareHeader(hWaveOut,pwh,sizeof(WAVEHDR)))←ここでもエラーが出る 
       HeapFree(GetProcessHeap(),0,pwh.lpData)←ここでエラーが出る 
でそのときのエラーメッセージは
「スレッド(&HAC8)でアクセス違反がありました(EPI=&H76AF1F22)。」
というような感じになっています。
投稿記事 Posted: 2008年8月09日(土) 22:13
  記事の件名:   引用付きで返信する
コード:
For i=0 TO SRATE 
    pwh.lpData(i)=(i番目のデータ)←省略している 
Next 
コード:
For i=0 TO SRATE-1
    pwh.lpData(i)=(i番目のデータ)←省略している 
Next 
にしてみたらどうなりますか?
投稿記事 Posted: 2008年8月09日(土) 14:15
  記事の件名:  返信ありがとうございます。  引用付きで返信する
返信ありがとうございます。
いろいろやっていたので返事が遅れてしまってすいません。
書き込み時に間違いがある、とのことでしたので、
書き込みの部分を調べてみました。
といっても書き込みを行う部分は前回投稿した部分のみなので
その辺で試したのですが、
コード:
ZeroMemory(VarPtr(pwh),sizeof(WAVEHDR)) 
pwh.lpData=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,SRATE)'SRATEは曲の長さ 
’ここをAとして
For i=0 TO SRATE 
    pwh.lpData(i)=(i番目のデータ)←省略している 
Next 
’ここをBとする。
pwh.dwBufferLength=SRATE 
pwh.dwFlags=WHDR_BEGINLOOP or WHDR_ENDLOOP 
pwh.dwLoops=1 
waveOutPrepareHeader(hwo,pwh,sizeof(WAVEHDR)) 
waveOutWrite(hwo,pwh,sizeof(WAVEHDR)) 
 
上のコードでAの部分でメモリの解放を行ったところ問題はなく、
Bで解放したところ例のエラーが出ました。
つまり書き込みのこの部分に問題があったとわかりました。
コード:
For i=0 TO SRATE 
    pwh.lpData(i)=(i番目のデータ)←省略している 
Next 
 
そうなると怪しいのが省略してしまった部分なのですが、よく見ると
型を間違えてました(オイ)。ポインタと値がごっちゃになってましたので修復しました。
しかしどういうわけかこれでも改善がされません。
実際のところエラーが発生する回数は減ったのですが、
稀にエラーが出ています。
回数が少なくなったのは良いですがデバッグがしずらいです。
省略部分は音の合成の部分なのですがやはり省略した部分が
悪いのでしょうか?といってもソースを曝さなきゃわかりませんが
カオス過ぎて時間がかかりそうなのでとりあえず現状を報告しました。
投稿記事 Posted: 2008年8月09日(土) 13:04
  記事の件名:  Re: メモリ解放時のエラー  引用付きで返信する
引用:
HEAP[wavelast_debug.exe]: Heap block at 00191D30 modified at 0019C97C past requested size of ac44
スレッド(&HDE0)のブレーク ポイント(EPI=&H77F75554)。
HEAP[wavelast_debug.exe]: Invalid Address specified to RtlFreeHeap( 00140000, 00191D38 )
スレッド(&HDE0)のブレーク ポイント(EPI=&H77F75554)。
この警告メッセージは、HeapAlloc() で確保した領域の外にまで値を書き込んでしまったときのものです。
プログラムが debug 版なら、メモリ解放時に領域周辺が汚されていないかチェックして、もし汚れていたらこのような警告を吐いてブレークします。

この手のバグは見つけ出すのが難しいことも多いですが・・・
とりあえず、その領域に書き込むコードを重点的に調べてみてください。
たとえば、書き込む前にそのポインタが正しく領域内を指しているか逐一チェックするなど。

# そういえば Assert ってないんですかね。
投稿記事 Posted: 2008年8月07日(木) 21:50
  記事の件名:  メモリ解放時のエラー  引用付きで返信する
waveoutをつかった音合成のプログラムを作っているのですが
debugするとメモリ解放時に
HEAP[wavelast_debug.exe]: Heap block at 00191D30 modified at 0019C97C past requested size of ac44
スレッド(&HDE0)のブレーク ポイント(EPI=&H77F75554)。
HEAP[wavelast_debug.exe]: Invalid Address specified to RtlFreeHeap( 00140000, 00191D38 )
スレッド(&HDE0)のブレーク ポイント(EPI=&H77F75554)。
というエラーが出ます。これってメモリのエラーですよね?
(経験上そう思う)

ところが実際にコンパイルしてみると正常に動作します。
しかしエラーが出る以上はやはり問題があると思います。
メモリ上のエラーは致命的なので何とかしたいです。

実はメモリやwaveoutはあまり知らないので
勉強しながらやっている状態です。
ソースをさらしたいのですが超ロングぐだぐだクソースなため
見せるに忍びないので重要そうな部分をさらします。

メモリ確保から演奏開始まで
コード:
ZeroMemory(VarPtr(pwh),sizeof(WAVEHDR))
pwh.lpData=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,SRATE)'SRATEは曲の長さ
For i=0 TO SRATE
    pwh.lpData(i)=(i番目のデータ)←省略している
Next
pwh.dwBufferLength=SRATE
pwh.dwFlags=WHDR_BEGINLOOP or WHDR_ENDLOOP
pwh.dwLoops=1
waveOutPrepareHeader(hwo,pwh,sizeof(WAVEHDR))
waveOutWrite(hwo,pwh,sizeof(WAVEHDR))

で問題となる終了時はコールバックにて
コード:
Function MainWndProc(hWnd As DWord, dwMsg As DWord, wParam As DWord, lParam As DWord) As DWord
	' TODO: この位置にウィンドウメッセージを処理するためのコードを記述します。
	Select Case dwMsg
      case MM_WOM_DONE
        waveOutUnprepareHeader(hWaveOut,pwh,sizeof(WAVEHDR))
        HeapFree(GetProcessHeap(),0,pwh.lpData)←ここでエラーが出る
waveoutではwaveOutUnprepareHeaderとHeapFreeは
プログラム終了時だけではなく、演奏終了時にやらないと
メモリ使用量が上昇してしまうので抜け目なくやっているつもりです。
実際メモリ使用量も上がったり下がったりで困っています。

・・・どうでも良いですが実はVer2.0辺りからABをやっていて
掲示板にもちょくちょく顔を出していたのですが、いつの間にか行かなくなり
ABもVer3.0~4.0初期しか使用しておらず、最近来て見たら
Ver5.0とかの話になってて時代の流れを感じました。
投稿記事 Posted: 2008年8月07日(木) 17:06

全ての表示時間は UTC+09:00 です


ページ移動:  
Powered by phpBB® Forum Software © phpBB Limited
Japanese translation principally by ocean