![]() |
Access Violation unter Win 10
Hallo zusammen,
ich habe mir ein kleines Programmchen geschrieben, was Morsecode "abspielt". Dazu nutze ich die BASS.dll. Funktioniert alles super. Nun wollte ich mein Programm meinen Freunden geben, die Windows 10 haben, ich selber arbeite auf Windows 8.1 Delphi XE3. Das Programm wirft bei ihnen beim drücken des Play-Buttons eine Access Violation aus. (Exception der Klasse $C00000005 mit der Meldung Read of adress 0x00000019). Unter Win 7 und 8.1 kommt dieser Fehler nicht. Ebenfalls kommt er nur in der Release-Version vor. Nun dachte ich, ich bin klug und debugge oldschool, mithilfe von ShowMessage oder ner Memo, nur durfte ich festestellen, dass es dann keine Exception mehr auswirft. Klar, könnte ich jetzt einfach ein unsichtbare Memo machen und immer eine Zeile schreiben, aber komisch ist die ganze sache schon, nur die Frage: Warum? Mit freundlichen Grüßen Hier die PlayButton Routine:
Delphi-Quellcode:
Und hier noch die Play Routine, falls das Problem dort ist (Achtung, etwas länger):
procedure TForm1.Button2Click(Sender: TObject);
var i: integer; begin Label11.Caption := 'Playing...'; // ShowMessage('1'); <-- Wenn aktiv, kein Fehler mehr //Memo1.Lines.Add('1'); <-- Wenn aktiv, kein Fehler mehr Button4.Enabled := true; Button2.Enabled := false; EnablePlaying(true); //schaltet manche Komponenten aus, die nicht gedrückt werden dürfen // ShowMessage('2'); <-- Wenn aktiv, kein Fehler mehr //Memo1.Lines.Add('2'); <-- Wenn aktiv, kein Fehler mehr Play(Richedit1.Lines,DitSettings,DahSettings,DitPool,DahPool); // ShowMessage('3'); <-- Wenn aktiv, kein Fehler mehr //Memo1.Lines.Add('3'); <-- Wenn aktiv, kein Fehler mehr for i := 0 to Length(DitPool) - 1 do BASS_ChannelStop(DitPool[i].SoundStream); for i := 0 to Length(DahPool) - 1 do BASS_ChannelStop(DahPool[i].SoundStream); Richedit1.SelectAll; Richedit1.SelAttributes.Color := clBlack; RichEdit1.SelLength := 0; EnablePlaying(false); Button2.Enabled := true; Button4.Enabled := false; Label11.Caption := 'Finished or Stopped'; end;
Delphi-Quellcode:
procedure TForm1.Play(Text: TStrings; DitRule, DahRule: TOutputSettings; DitSound,DahSound: TAudioFileArray);
var i,i2: Integer; CurrAudio,BeforeAudio: TAudioFile; DitBefore,DahBefore,Dur: integer; begin DitBefore := 0; DahBefore := 0; { for i := 0 to Length(DitSound) - 1 do BASS_ChannelSetAttribute(DitSound[i].SoundStream,BASS_ATTRIB_VOL,Volume); for i := 0 to Length(DahSound) - 1 do BASS_ChannelSetAttribute(DahSound[i].SoundStream,BASS_ATTRIB_VOL,Volume); } for i := 0 to Text.Count - 1 do begin for i2 := 1 to Length(Text[i]) do begin RichEdit1.SelStart := i2 - 1; RichEdit1.SelLength := 1; RichEdit1.SelAttributes.Color := clRed; // Richedit1.ClearSelection; case Text[i][i2] of '.': begin case DitRule.Rules of prRandom: begin CurrAudio := DitSound[Random(Length(DitSound) - 1)]; end; prOrder: begin if DitBefore = Length(DitSound) - 1 then DitBefore := -1; CurrAudio := DitSound[DitBefore + 1]; Inc(DitBefore); end; prSingleOnly: begin CurrAudio := DitSound[0]; end; end; case BeforeAudio.PlayHandling of phWait: begin while BASS_ChannelIsActive(BeforeAudio.SoundStream) = BASS_ACTIVE_PLAYING do begin Idle(10); end; end; phContinue: begin end; phPause: begin BASS_ChannelPause(BeforeAudio.SoundStream); end; phStop: begin BASS_ChannelStop(BeforeAudio.SoundStream); end; end; if CurrAudio.PlayHandling = phPause then BASS_ChannelPlay(CurrAudio.SoundStream,false) else BASS_ChannelPlay(CurrAudio.SoundStream,true); BeforeAudio := CurrAudio; if CurrAudio.PlayHandling <> phWait then begin if DitRule.Variance then Idle(DitRule.Duration + Random(DitRule.VarianceValue)) else Idle(DitRule.Duration); end; end; '-': begin case DahRule.Rules of prRandom: begin CurrAudio := DahSound[Random(Length(DahSound) - 1)]; end; prOrder: begin if DahBefore = Length(DahSound) - 1 then DahBefore := -1; CurrAudio := DahSound[DahBefore + 1]; Inc(DahBefore); end; prSingleOnly: begin CurrAudio := DahSound[0]; end; end; case BeforeAudio.PlayHandling of phWait: begin while BASS_ChannelIsActive(BeforeAudio.SoundStream) = BASS_ACTIVE_PLAYING do begin Idle(10); end; end; phContinue: begin end; phPause: begin BASS_ChannelPause(BeforeAudio.SoundStream); end; phStop: begin BASS_ChannelStop(BeforeAudio.SoundStream); end; end; if CurrAudio.PlayHandling = phPause then BASS_ChannelPlay(CurrAudio.SoundStream,false) else BASS_ChannelPlay(CurrAudio.SoundStream,true); BeforeAudio := CurrAudio; if CurrAudio.PlayHandling <> phWait then begin if DahRule.Variance then Idle(DahRule.Duration + Random(DahRule.VarianceValue)) else Idle(DahRule.Duration); end; end; ' ': begin case BeforeAudio.PlayHandling of phWait: begin while BASS_ChannelIsActive(BeforeAudio.SoundStream) = BASS_ACTIVE_PLAYING do begin Idle(10); end; end; phContinue: begin end; phPause: begin BASS_ChannelPause(BeforeAudio.SoundStream); end; phStop: begin BASS_ChannelStop(BeforeAudio.SoundStream); end; end; Idle(BetterSpinedit5.Value); end; '/': begin case BeforeAudio.PlayHandling of phWait: begin while BASS_ChannelIsActive(BeforeAudio.SoundStream) = BASS_ACTIVE_PLAYING do begin Idle(10); end; end; phContinue: begin end; phPause: begin BASS_ChannelPause(BeforeAudio.SoundStream); end; phStop: begin BASS_ChannelStop(BeforeAudio.SoundStream); end; end; Idle(BetterSpinedit6.Value); end; '#': begin end; end; if Stop then begin Stop := false; exit; end; RichEdit1.SelStart := i2 - 1; RichEdit1.SelLength := 1; RichEdit1.SelAttributes.Color := clLime; // Richedit1.ClearSelection; end; if Stop then begin Stop := false; exit; end; end; end; |
AW: Access Violation unter Win 10
Ok, hätte vielleicht warten können mit dem Thread.
Hat sich geklärt, nach weiterem Debuggen habe ich herausgefunden, dass
Delphi-Quellcode:
scheinbar die Exception beim ersten Durchlauf wirft, sprich, wenn
case BeforeAudio.PlayHandling of
phWait: begin while BASS_ChannelIsActive(BeforeAudio.SoundStream) = BASS_ACTIVE_PLAYING do begin Idle(10); end; end; phContinue: begin end; phPause: begin BASS_ChannelPause(BeforeAudio.SoundStream); end; phStop: begin BASS_ChannelStop(BeforeAudio.SoundStream); end; end;
Delphi-Quellcode:
undefiniert, aber nicht NIL ist. Im Debug springt Delphi scheinbar in case-Schleifen bei ungültigen Werten einfach weiter und unter Win 7 und 8.1 auch. Warum ein ShowMessage vor dem Aufruf der Play-Routine (aber nicht innerhalb der Play Routine) das verhindert, ist mir schleierhaft, aber okay.
BeforeAudio
Mit freundlichen Grüßen |
AW: Access Violation unter Win 10
Hallo,
da hättest Du doch eine Compilerwarnung bekommen müssen? Win10 prüft die Exe'n viel stärker auf Speicherüberschreibung und Zugriffe auf nicht erlaubte Bereiche, also wie bei dir mit dem Zugriff auf eine nicht initialisiertes Objekt. Ich empfehle dann immmer "Nimm MadExcept". |
AW: Access Violation unter Win 10
Ne nicht okay
Vielleicht fängst Du mal an, Warnungen und Hinweise des Compilers nicht zu ignorieren. ;-) |
AW: Access Violation unter Win 10
Hallo,
@hoika Ja, habe ich, nur achte ich nicht auf Compilerhinweise, solange das Programm in seiner Grundstruktur nicht läuft. Warnungen schau ich schon öfter an, nur waren die auch bisher unbedeutend für mich, da das meistens Warnungen waren, wie "xyz ist möglicherise nicht initialiesiert worden" wo ich daneben sitze und sage "Jein. Ich weise einen anderen zu, garantiert. Ergo Warnung unbedeutend". Schon Karma, dass es dieses Mal der Fehler war. @freimatz Doch ist okay, hab ja den Fehler gefunden. Die Hinweise und insbesondere die Warnungen sind für mich nie ein Problem gewesen. Da da auch so Sachen sind wie "xyz ist möglicherise nicht initialiesiert worden", was ich vorher aber in jedem Fall zuweise, ignorier ich die öfter mal. Wenn ich dann sehr viele Warnungen und Hinweise habe, habe ich auch keine Lust, die durchzugehen und zu gucken ob möglicherweise einer davon mein Problem verursacht. Da geht es schneller, wenn ich das schnell durchdebugge. |
AW: Access Violation unter Win 10
Hallo,
Zitat:
gerade bei Objekten. |
AW: Access Violation unter Win 10
Wenn Dateigröße egal ist würde ich anders vorgehen um OS Probleme zu vermeiden:
Wandel dein Ton in WAV/PCM und steig auf PlaySound() um, binde die Waves als Resource ein, spiele mit PlaySound die Resource, schmeiss Bass.dll raus, fertig. edit Ps: Falls Du nicht Wissen solltest wie, ich kann gerne ein Beispiel teilen das Dir alle Grundlagen Erklärt da ich erst Gestern mir selbst so etwas geschrieben habe, allerdings als eigener Thread, damit bei mir etwas solange wie der Ton spielt Unterdrückt bzw nach Ton erst freigegeben wird, und das App nicht hängt während Thread aufs Ton-Ende wartet. |
AW: Access Violation unter Win 10
Hallo,
@hoika Naja, selbstverständlich bin ich selber schuld, ist ja mein Code. Hier kurz zum Verständnis: Ich habe zwei Arrays, ein Dit und ein Dah Array of TAudioFile. Da stehen alle möglichen Sachen zu Audiodateien drinne. Nun brauche ich für meine Routine den Sound, der zuletzt gespielt wurde, ergo ich übergebe das aktuelle Arrayglied an eine Variable und lese die später aus. Das hat ein Problem verursacht, was mir nicht bekannt war (ich habe zum ersten Mal mit eigenen Objekten gearbeitet und musste erst rausfinden, dass man in einer Variable des Typen nur einen Pointer auf den Speicher schreibt und nicht den Typ mit all seinen propertys selber, stört ja aber für meinen Anwendungszweck garnicht), was ja jetzt auch gelöst ist. Nun habe ich einen Record, aus dem ich Spielanweisungen auslese. Dieser wird im OnCreate beschrieben und später nur noch mit (garantiert gültigen) Werten überschrieben. Dann lese ich aus diesem Record aus und verwende Daten darin. Jetzt sagt mir Delphi, dass diese Variable, die den Inhalt eines (in jedem Fall beschriebenen) Records beinhaltet, möglicherweise nicht initialisiert wird. Was auch immer das in diesem Zusammenhang bedeutet. @KodeZwerg Ja, nee, soll eher so ablaufen, dass der Benutzer selber Sounds reinladen kann. Da .mp3 und .wav da recht verbreitet ist und ich bei "Delphi MP3 abspielen" so gut wie immer nur auf BASS gestoßen bin, hab ich mich da (in einer abgeschwächten Version) "reingefuchst". Insofern man mit deiner Methode zur Runtime Sounds individuell laden, abspielen und Sachen wie Lautstärke ändern kann, würde ich mir die gerne auch mal anschauen. |
AW: Access Violation unter Win 10
Nein, mein Beispiel würde sich auf das Wave Dateiformat beschränken, lese mal
![]() Laut Leise Repeat Shuffle Record Convert Upload Download Tags WasAuchImmer, all das muss wenn gewünscht selber nachgerüstet werden, in wie fern da was Möglich ist entnehme bitte MSDN. Die einzige Postive Nachricht zu Deinen Fragen, man muss nicht Resource verwenden, Du kannst auch während Laufzeit aus Resource einen Dateinamen übergeben. So wie "schau in Ordner X ob es Datei Y gibt, wenn nicht dann benutze Resource." Erweiterbar indem Du User eine x-beliebige Datei aussuchen lässt. Irgendwie so etwas. Ich will damit Bass nicht schlecht machen aber um ein "pieps"-Geräusch abzuspielen bedarf es halt keiner großen Bibliothek, darauf wollte ich hinaus, mit Bass, korrekte Handhabung Vorausgesetzt, ist natürlich alles viel flexibler und universeller Nutzbar und vor allem Erweiterbarer aber im gleichen Augenblick bist Du auch an Bass gebunden, falls ein OS Update dieses kaputt macht hast Du ein Problem. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:55 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz