AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi Access Violation bei Sendmessage nach einiger Zeit?!
Thema durchsuchen
Ansicht
Themen-Optionen

Access Violation bei Sendmessage nach einiger Zeit?!

Ein Thema von Anthauri · begonnen am 2. Jan 2008 · letzter Beitrag vom 2. Jan 2008
Antwort Antwort
Anthauri

Registriert seit: 1. Feb 2004
61 Beiträge
 
Delphi 6 Personal
 
#1

Access Violation bei Sendmessage nach einiger Zeit?!

  Alt 2. Jan 2008, 14:50
Hallo zusammen,

ich habe ein (für mich) ziemlich mysteriöses Problem:

Ich habe drei Programme am laufen. Das eine dient zur Verwaltung von bestimmten Daten (in diesem Fall eine Playlist mit Musikstücken). Die anderen beiden enthalten jeweils den eigentlichen Player.
Das Hauptprogramm übergibt Nachrichten an die beiden Player wie "lade Lied ...", "setze Lautstärke..." etc.
Der Sinn des Programms liegt darin, dass die Liste mit Musikstücken abgearbeitet werden soll. Jeweils vor dem Ende des einen Liedes wird das nächste Lied auf dem anderen Player gestartet und die Lautstärke des einen gesenkt während die andere erhöht wird - ein faden also.

Im Hauptprogramm gibt es zwei Prozeduren für das versenden der Daten und zwei zum Empfangen (eine für jeden Player). Im jeweiligen Player gibt es je eine Prozedur zum versenden und eine zum empfangen.

Soweit alles gut, alles geht perfekt.


Wenn das Hauptprogramm aber einige Zeit gelaufen ist, kommt eine Access Violation at (irgendeine Adresse) write0000000.

Genaugenommen kommen nacheinander sehr viele solche Meldungen, die teilweise andere Adressen als die erste Meldung haben, dann wird auch über ein READ statt WRITE gemeckert.
Die Programme kann ich dann nur noch "Hart" beenden.

Das Hauptprogramm übergibt (abgesehen von den Fade-Vorgang) eher selten Daten an die anderen Progs.
Das Fading erfolgt in 100 Schritten - und somit 100 Messages (Prozent halt) und läuft in 5 Sekunden ab. Die Player übergeben an das Hauptprog (sofern sie etwas abspielen) die aktuelle Position alle 500 Millisekunden.

Wie gesagt im Großen und Ganzen gehts aber halt nach einiger Laufzeit nicht mehr (etwa 30-45 Min)

Für das Senden / Empfangen vom Hauptprogramm zum Player 1 wird WM_User + 1
Für das Senden / Empfangen vom Hauptprogramm zum Player 1 wird WM_User + 2
Für das Senden / Empfangen vom Player 1 zum Hauptprogramm wird WM_User + 3
Für das Senden / Empfangen vom Player 2 zum Hauptprogramm wird WM_User + 4

benutzt. Ansonsten sind die einzelnen Prozeduren sehr ähnlich aufgebaut.

Die Inhalte der Prozeduren basieren im wesentlichen auf Hinweisen aus dem Forum.
Leider habe ich keine Ahnung warum der Fehler auftritt - bzw. warum er nicht sofort auftritt.


Kann es sein, dass die Speicherbereiche irgendwie zu eng aneinanderliegen und so ein ungewolltes Kaputtmachen der Daten erfolgt?
Oder muß etwas bei dem CreateFileMapping beachtet werden (da steht ja immer der gleiche Wert drin)?
Was genau gibt der WM_User eigentlich an (Bytes)? oder ist das nur so ne Art ID?
Muß ich irgendwie die Länge der Nachrichten bei der Deklaration beachten?


Kann jemand helfen?
Wahrscheinlich habe ich Tomaten auf den Augen oder so.


Hauptprogramm:
Delphi-Quellcode:
procedure TMix_Player_f.Send_Message_Player_1(Sender: TObject);
var LHandle: Cardinal;
begin
  fFileHandle_s1 := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0, length(sendtext_1) + 1, 'Player1');
  if fFileHandle_s1 <> 0 then
  begin
    FSpeicher := MapViewOfFile(fFileHandle_s1, FILE_MAP_WRITE, 0, 0, 0);
    StrCopy(FSpeicher, PChar(sendtext_1));
    LHandle := FindWindow('TMixPlayer_1_f', nil);
    if LHandle <> 0 then
    begin
      SendMessage(LHandle, WM_USER + 1, 0, 0);
    end;
    CloseHandle(fFileHandle_s1);
  end;
end;
Delphi-Quellcode:
procedure TMix_Player_f.Send_Message_Player_2(Sender: TObject);
var LHandle: Cardinal;
begin
  fFileHandle_s2 := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0, length(sendtext_2) + 1, 'Player2');
  if fFileHandle_s2 <> 0 then
  begin
    FSpeicher := MapViewOfFile(fFileHandle_s2, FILE_MAP_WRITE, 0, 0, 0);
    StrCopy(FSpeicher, PChar(sendtext_2));
    LHandle := FindWindow('TMixPlayer_2_f', nil);
    if LHandle <> 0 then
    begin
      SendMessage(LHandle, WM_USER + 2, 0, 0);
    end;
    CloseHandle(fFileHandle_s2);
  end;
end;
Delphi-Quellcode:
procedure TMix_Player_f.FDatenEmpfang1(var AMessage: TMessage);
var LSpeicher: PChar;
    LDest: String;
begin
  fFileHandle_e1 := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0, 500, 'Control1');
  if fFileHandle_e1 <> 0 then
  begin
    LSpeicher := MapViewOfFile(fFileHandle_e1, FILE_MAP_WRITE, 0, 0, 0);
    setlength(LDest, length(LSpeicher));
    StrCopy(PChar(LDest), LSpeicher);
    cometext1 := LDest;
    workmessage1;
    CloseHandle(fFileHandle_e1);
  end;
end;
Delphi-Quellcode:
procedure TMix_Player_f.FDatenEmpfang2(var AMessage: TMessage);
var LSpeicher: PChar;
    LDest: String;
begin
  fFileHandle_e2 := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0, 500, 'Control2');
  if fFileHandle_e2 <> 0 then
  begin
    LSpeicher := MapViewOfFile(fFileHandle_e2, FILE_MAP_WRITE, 0, 0, 0);
    setlength(LDest, length(LSpeicher));
    StrCopy(PChar(LDest), LSpeicher);
    cometext2 := LDest;
    workmessage2;
    CloseHandle(fFileHandle_e2);
  end;
end;
Player1:
Delphi-Quellcode:
procedure TMixPlayer_1_f.Player_SendMessages(Sender: TObject);
var LHandle: Cardinal;
begin
  fFileHandle_s1 := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0, length(sendtext) + 1, 'Control1');
  if fFileHandle_s1 <> 0 then
  begin
    FSpeicher := MapViewOfFile(fFileHandle_s1, FILE_MAP_WRITE, 0, 0, 0);
    StrCopy(FSpeicher, PChar(sendtext));
    LHandle := FindWindow('TMix_Player_f', nil);
    if LHandle <> 0 then
    begin
      SendMessage(LHandle, WM_USER + 3, 0, 0);
    end;
    CloseHandle(fFileHandle_s1);
  end;
end;
Delphi-Quellcode:
procedure TMixPlayer_1_f.FDatenEmpfang(var AMessage: TMessage);
var LSpeicher: PChar;
    LDest: String;
begin
  fFileHandle_e1 := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0, 500, 'Player1');
  if fFileHandle_e1 <> 0 then
  begin
    LSpeicher := MapViewOfFile(fFileHandle_e1, FILE_MAP_WRITE, 0, 0, 0);
    setlength(LDest, length(LSpeicher));
    StrCopy(PChar(LDest), LSpeicher);
    cometext := LDest;
    if checkbox1.Checked = true
    then listbox1.items.append(LDest);

    work_message;
    CloseHandle(fFileHandle_e1);
  end;
end;
Player2:
Delphi-Quellcode:
procedure TMixPlayer_2_f.Player_SendMessages(Sender: TObject);
var LHandle: Cardinal;
begin
  fFileHandle_s1 := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0, length(sendtext) + 1, 'Control2');
  if fFileHandle_s1 <> 0 then
  begin
    FSpeicher := MapViewOfFile(fFileHandle_s1, FILE_MAP_WRITE, 0, 0, 0);
    StrCopy(FSpeicher, PChar(sendtext));
    LHandle := FindWindow('TMix_Player_f', nil);
    if LHandle <> 0 then
    begin
      SendMessage(LHandle, WM_USER + 4, 0, 0);
    end;
    CloseHandle(fFileHandle_s1);
  end;
end;
Delphi-Quellcode:
procedure TMixPlayer_2_f.FDatenEmpfang(var AMessage: TMessage);
var LSpeicher: PChar;
    LDest: String;
begin
  fFileHandle_e1 := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0, 500, 'Player2');
  if fFileHandle_e1 <> 0 then
  begin
    LSpeicher := MapViewOfFile(fFileHandle_e1, FILE_MAP_WRITE, 0, 0, 0);
    setlength(LDest, length(LSpeicher));
    StrCopy(PChar(LDest), LSpeicher);
    cometext := LDest;
    if checkbox1.Checked = true
    then listbox1.items.append(LDest);

    work_message;
    CloseHandle(fFileHandle_e1);
  end;
end;
  Mit Zitat antworten Zitat
Benutzerbild von SirThornberry
SirThornberry
(Moderator)

Registriert seit: 23. Sep 2003
Ort: Bockwen
12.235 Beiträge
 
Delphi 2006 Professional
 
#2

Re: Access Violation bei Sendmessage nach einiger Zeit?!

  Alt 2. Jan 2008, 14:52
die Adresse deutet darauf hinn das du eine Variable verwendest welche nil ist und damit hantierst. Es wird also nicht das Empfangen und Senden von Nachrichten schief gehen sondern du schreibst schlicht und einfach an Adresse 0. Was mit in diesem Zusammenhang auffällt ist das du gar nicht prüfst ob der Rückgabewert von MapViewOfFile gültig ist sondern du arbeitest einfach damit. Wenn der Aufruf jedoch fehl geschlagen ist kommt genau der Fehler.

Verwendest du nirgends ein UnmapViewOfFile?
Jens
Mit Source ist es wie mit Kunst - Hauptsache der Künstler versteht's
  Mit Zitat antworten Zitat
Nuclear-Ping
(Gast)

n/a Beiträge
 
#3

Re: Access Violation bei Sendmessage nach einiger Zeit?!

  Alt 2. Jan 2008, 14:54
Ich hab deine Codes nur überflogen. Ich gehe nicht davon aus, dass SendMessage eine Zugriffsverletzung auslösen kann.

"Write of Address 00000000" sagt auch aus, dass versucht wird, in einen nicht-reservierten / nicht-existenten Speicherbereich zu schreiben.
  Mit Zitat antworten Zitat
Anthauri

Registriert seit: 1. Feb 2004
61 Beiträge
 
Delphi 6 Personal
 
#4

Re: Access Violation bei Sendmessage nach einiger Zeit?!

  Alt 2. Jan 2008, 15:10
Vielleicht ist das Unmpa ja mit das Problem,
denn die Variablen mit den zu übertragenden Strings wurden davor ja auch benutzt. Irgendwas sollte da also drin sein, oder?

Wie gesagt ist der Code relativ blind abgetippt. In den Beispielen war kein Unmap drin.

Wie prüfe ich den Wert des MapViewOfFile denn und wo muß ich das unmappen und wie?

Ich kann (und sollte) wohl den String auf NIL prüfen bevor ich damit was mache - wenn das damit gemeint ist. Ich wußte aber gar nicht, dass ein String NIL sein kann.

Übrigens...mann seit ihr schnell im antworten.
  Mit Zitat antworten Zitat
Benutzerbild von SirThornberry
SirThornberry
(Moderator)

Registriert seit: 23. Sep 2003
Ort: Bockwen
12.235 Beiträge
 
Delphi 2006 Professional
 
#5

Re: Access Violation bei Sendmessage nach einiger Zeit?!

  Alt 2. Jan 2008, 15:45
Schau am besten mal in der Hilfe was MapViewOfFile macht und dir zurück gibt. Du solltest also überprüfen ob MapViewOfFile erfolgreich war. Und UnMapViewOfFile solltest du dann aufrufen wenn du den Speicher nicht mehr brauchst.
Der Fehler kann durchaus daher kommen denn wenn du Speicher nicht frei gibst ist irgendwann keiner mehr übrig um neues darein zu laden.

Das allerbeste ist du versuchst die Quelltexte zu verstehen (also nicht nur abtippen), dann weißt du auch wo du zum optimieren ansetzen kannst du wo du Fehler beheben musst.
Jens
Mit Source ist es wie mit Kunst - Hauptsache der Künstler versteht's
  Mit Zitat antworten Zitat
Anthauri

Registriert seit: 1. Feb 2004
61 Beiträge
 
Delphi 6 Personal
 
#6

Re: Access Violation bei Sendmessage nach einiger Zeit?!

  Alt 2. Jan 2008, 16:43
Hallo und danke für die Antworten...

Um dem falschen Bild vorzubeugen...
Dass es nicht sinnvoll ist einfach etwas abzuschreiben ist mir klar - ich versuche auch stets derartiges zu vermeiden und die Beiträge zu kapieren anstatt sie blind anzuwenden.
Manchmal war mir aber kein anderer Weg möglich.

Zum "Sendmessage" habe ich hier im Forum auch zunächst gesucht und gelesen.
Dabei fiel es mir teilweise aber schwer aus der Vielzahl von Beispielen, die dann teilweise doch inhaltlich voneinander abweichen, die relevanten Dinge zu extrahieren.
Ausprobiert hatte ich auch verschiedene Varianten.

Es gibt auch Beispiele, die ein Unmap benutzen - aber eben auch welche ohne.
Es gibt welche mit Prüfungen - aber auch welche ohne.

Ich habe dabei aber kein Beispiel gefunden das (vielleicht liegt es an mir) hinreichend erklärt was z.B. das WM_User genau angibt oder warum bei dem CreateFileMapping($FFFFFFFF) und nicht etwas anderes steht.

Immer wenn ihr von der Hilfe scheibt, gehe ich davon aus, dass diejenige Hilfe gemeint ist, die ich vom Delphi-Editor über das Menu "Help/Delphi Help" über die passenden Links in der Programmgruppe "Start/Programme/Borland/Delphi6/Help" oder durch drücken von F1 auf dem Befehl aufrufen kann. Mir ist schon mehrfach aufgefallen, dass ich da verschiedene Begriffe nicht wiederfinde auf die verwiesen wird (z.B. MapViewOfFile).

Kann auch das an der Personal Edition liegen? - Wie dem auch sei.


Dass man schon auf die Datenvalidierung achten sollte ist mir auch klar. Ich war aber davon ausgegangen (da ich ihn selbst fülle), dass in dem String, den ich senden will immer etwas drin ist.
Dass das Mapping selbst auf NIL zu prüfen ist hatte ich nicht vermutet - muß man aber wohl bei solchen Arbeiten mit dem Speicher immer machen.

Ich lerne halt noch.

Ich habe nun Abfragen auf NIL implementiert und nutze ein Unmap an den entsprechenden stellen - mal sehen ob das hilft.

Vielen Dank.
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#7

Re: Access Violation bei Sendmessage nach einiger Zeit?!

  Alt 2. Jan 2008, 17:23
Hinweis: Bei den MMF gibt es auch eine AV, wenn versucht wird hinter dem gemappten Speicher zu zu greifen. Auch wenn der Speicher nur zum Schreiben geöffnet wurde und man dann lesen drauf zugreift (und umgekehrt). Von daher auch mal dieses mit in Betracth ziehen.
  Mit Zitat antworten Zitat
Nuclear-Ping
(Gast)

n/a Beiträge
 
#8

Re: Access Violation bei Sendmessage nach einiger Zeit?!

  Alt 2. Jan 2008, 17:59
Zitat von Anthauri:
[...] Ich kann (und sollte) wohl den String auf NIL prüfen bevor ich damit was mache - wenn das damit gemeint ist. Ich wußte aber gar nicht, dass ein String NIL sein kann. [...]
Es ist ja auch ein PChar, also ein Zeiger auf eine (nullterminierte) Zeichenkette. Und der kann nil sein.
  Mit Zitat antworten Zitat
Benutzerbild von SirThornberry
SirThornberry
(Moderator)

Registriert seit: 23. Sep 2003
Ort: Bockwen
12.235 Beiträge
 
Delphi 2006 Professional
 
#9

Re: Access Violation bei Sendmessage nach einiger Zeit?!

  Alt 2. Jan 2008, 18:34
@Muetze: Dann würde aber keine Zugriffsverletzung an Adresse 0 kommen
Jens
Mit Source ist es wie mit Kunst - Hauptsache der Künstler versteht's
  Mit Zitat antworten Zitat
Anthauri

Registriert seit: 1. Feb 2004
61 Beiträge
 
Delphi 6 Personal
 
#10

Re: Access Violation bei Sendmessage nach einiger Zeit?!

  Alt 2. Jan 2008, 20:02
Auf jeden Fall hat nun alles geklappt, die Meldungen sind "wech" und der Player dudelte zwei volle Stunden vor sich hin.

Möglicherweise waren ja beide Fehler meinerseits die Ursache (fehlende Abfrage auf NIL und fehlendes Unmap)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:36 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz