Bis Mittag war heute alles O.K. Mein Programm unter Visual Studio
lief ohne Probleme. Nach dem heutigen Update von Visual Studio
läuft mein Programm nicht mehr. Ein Fehler nach dem Start mit
Debug und der andere ohne Debug…
B. P. schrieb:> Nach dem heutigen Update von Visual Studio> läuft mein Programm nicht mehr. Ein Fehler nach dem Start mit> Debug und der andere ohne Debug…
Hast du schon versucht das Programm KOMPLETT neu zu Compilieren?
Also die Projektmappe einmal bereinigt und dann BuildAll?
Gruß
Carsten
Wenn Du das Programm auf dem Rechner laufen lässt, auf dem Du es auch
kompiliert hast, wird im zweiten Fall der zum Visual Studio gehörende
JIT-Debugger aufgerufen, wenn Du auf den Knopf "Wiederholen" klickst.
Dann kannst Du sehen, was schiefgeht.
Wenn das Problem in irgendeiner DLL auftritt, sieh Dir den Stacktrace
an, irgendwo dort wird Dein Code zu finden sein, der eine Funktion aus
der DLL aufruft; sieh Dir die Funktionsargumente etc. genauer an.
Manchmal war es auch schon hilfreich, die .suo-Datei des Projektes zu
löschen. Da sind irgendwelche Nutzer-bezogenen Daten drin. Vielleicht
vorsichtshalber mal ein Backup machen.
Die Lösung. Ich habe den Visual Studio Installer gestartet
(In der Suchleiste tippen…). Mit „mehr“ weitere Option stehen
zu Verfügung.Zuerst habe ich die Option Reparatur gewählt
( mit der Vermutung,dass das nur Installationsfehler war).
Das Ergebnis war leider weiter,wie auf meinem Screenshot zu
sehen ist. Die nächste Option, die ich ausgewählt habe, war
"Visual Studio zurückrollen".Danach war ich zurück zu der
Version vor dem Update. Jetzt läuft alles ohne Fehler.
Ich programmiere nur C++/CLI mit Forms.
B. P. schrieb:> Die Lösung.
Du magst es als Lösung ansehen, ich sehe das anders. Du bist jetzt
einfach auf den alten Stand zurückgegangen.
Ich glaube eher, dass das Übersetzen Deines Codes im aktuellen Visual
Studio einen Speicher-Überschreiber aufgedeckt hat, der durch einen
anders übersetzenden/optimierenden Compiler zu Tage getreten ist. Durch
das Rücksetzen auf den alten Stand hast Du den potentiellen Fehler
einfach wieder überdeckt.
So kann man natürlich auch Probleme lösen. Wenn Du Pech hast, holt Dich
der Fehler irgendwann wieder ein. ;-)
Frank M. schrieb:> Du magst es als Lösung ansehen, ich sehe das anders. Du bist jetzt> einfach auf den alten Stand zurückgegangen.
Wenn ein Update da ist, dann nutze ich ihn immer. Jedes Programm hat
Potenzial für Fehler. Auch Visual Studio. Ich allokiere in meinem
Programm Speicher mit drei Funktionen: malloc(), HeapAlloc(), und
VirtualAlloc().Kein Compiler kann voraus feststellen,ob beim Zugriff auf
allokierten Speicher zur Verletzung kommt. Kein Compiler kann sogar
feststellen ob wirklich zum Allokieren kommt auch wenn alle drei
Funktion
im Programmcode erscheinen. Einzige Tatsache die Compiler feststellen
kann, ist dass das solche Art von Allokieren passieren kann und das mit
Fehlermeldung verbieten.Dazu ist aber nicht gekommen. Das „Erstellen“
lief Fehlerfrei. Das Programm wurde danach aber nicht gestartet. Das
kann ich im Moment als Fehler auf Microsoft Seite interpretieren.
B. P. schrieb:> Das Programm wurde danach aber nicht gestartet.
Meine Güte -- nutze den Debugger! Der ist dafür da, damit Du den Fehler
in Deinem Code finden kannst.
Harald K. schrieb:> Meine Güte -- nutze den Debugger! Der ist dafür da, damit Du den Fehler> in Deinem Code finden kannst.
Aber das Programm startet nicht...
B. P. schrieb:> Kein Compiler kann voraus feststellen,ob beim Zugriff auf allokierten> Speicher zur Verletzung kommt.
Natürlich nicht. Aber ein neuerer Compiler kann den Code anders
optimieren und auch den allokierten Speicher anders anordnen, so dass
ein Buffer-Overflow in Deinem Code nun Bereiche kaputtschreibt, die
vorher nicht betroffen waren.
Das heißt: Mit großer Wahrscheinlichkeit hast Du mit dem alten Visual
Studio einfach nur Glück, dass es zufällig läuft. Das neue VS gibt Dir
nun die Chance, den Fehler zu finden. Ich würde diese nutzen statt
einfach den Mantel der Ignoranz drüber zu legen.
> Das kann ich im Moment als Fehler auf Microsoft Seite interpretieren.
Hier wurden schon viele Threads aufgemacht mit sehr vielen angeblichen
Compilerfehlern, die zum Beispiel dem gcc angedichtet wurden. Wie sich
am Ende zu 99,5% herausgestellt hat, war nicht der Compiler schuld,
sondern der Programmierer.
B. P. schrieb:> Aber das Programm startet nicht...
Heißt Dein Programm etwa nicht BMPinPCB.exe? In deinem Screenshot steht,
dass dieses Programm auf die Speicherstelle -1 zugreift. Also wird es
auch gestartet, leider aber auch sehr schnell wegen Zugriffsverletzung
wieder beendet.
B. P. schrieb:> Aber das Programm startet nicht...
Tut es, denn es wird die von Dir gepostete Fehlermeldung ausgegeben.
Mit dem von mir schon heut früh erwähnten Knopf "Wiederholen".
Und wenn das nicht hilft, gibt es in Deiner IDE eine Funktion, um das
Programm aus der IDE heraus zu starten. Es gibt sogar eine, die "step
into" heißt, damit kannst Du Deinem Programm Schritt für Schritt
zusehen.
B. P. schrieb:
> Kein Compiler kann voraus feststellen,ob beim Zugriff auf allokierten> Speicher zur Verletzung kommt.
Aber ein Compiler kann Code erzeugen der an den Bereichs Enden eine
Signatur anhängt und auf überschreiben testet. Das ist aber nichts neues
...
Meine bescheidene Meinung: Wenn es früher "ging" und nach deinem Update
nicht mehr, dann ist das natürlich schlecht, muß aber erstmal kein
"Programmierfehler" sein. Ferndiagnosen sind auch immer so eine Sache.
Ich sehe also nur "Expression: _CrtIsValidHeapPointer(block)".
Es könnte sein (Achtung Ferndiagnose), daß das neu kompilierte Programm
mit seiner "neuen" RuntimeLib vom User geladene DLLs benutzt, die
wiederum eine eigene RuntimeLib benutzen, die jetzt nicht mehr
untereinander kompatibel sind. Das wäre dann Punkt D im unten verlinkten
Artikel. Alles andere möchte ich bald (Achtung Ferndiagnose)
ausschließen, denn doppelte free()'s wären sicher schon früher mal
aufgefallen.
Es könnte sein, daß das Neu-Kompilieren des Programms mit einer älteren
"Windows-SDK-Version" in den Projekteinstellungen das Problem behebt.
Ein anderer Quell der Freude nach VS-Updates ist diese Zeile in den
Projektfiles:
<VCToolsVersion>14.36.32532</VCToolsVersion>
Aber wenn diese Nummer nicht stimmt (letztendlich der Dateipfad nicht
gefunden wird), wird das Projekt ja gar nicht erst geöffnet.
https://stackoverflow.com/questions/64418624/why-do-i-get-crtisvalidheappointerblock-and-or-is-block-type-validheader-b
Heiko schrieb:> Meine bescheidene Meinung: Wenn es früher "ging" und nach deinem Update> nicht mehr, dann ist das natürlich schlecht, muß aber erstmal kein> "Programmierfehler"
Mein Windows Programm ist Ereignisgesteuert. Nach dem Start wird
kein Code von meinem Programm Teil ausgeführt aber nur das, was
Visual Studio für GUI Forms vorbereitet hat. Es wird kein Speicher
allokiert. Erst nach dem Bildaufbau fertig ist kann man durch
Button Aktion anleiten und erst dann wird der Speicher allokiert.
Mein (intuitives…) Verdacht geht in die Richtung von Verwendung von
malloc(). So etwas passieren kann wenn mehrere Entwickler an
verschiedenen Fronten einer Entwicklung arbeiten.
Das was ein Entwickler in Compiler zugelassen hat, ein anderer beim
Debuggen abgelehnt hat...
Mal abgesehen davon, daß ich das Problem verstehe, verstehe ich auch
nicht so recht, wo das Problem mit dem Debuggen ist.
Die Frage ist doch, wie weit das Programm nach dem Start überhaupt
kommt. Wird WinMain() überhaupt erreicht, damit etwas später überhaupt
ein Window aufgemacht werden kann. Das OS ruft den "EntryPoint" des
Programms (oder einer DLL) auf. Üblicherweise ist das Code einer
C-Runtimelib. Erst wenn die mit ihrem Init-Zeug fertig ist, wird WinMain
aufgerufen.
Also mal einen Breakpoint direkt an den Anfang von WinMain setzen. Wenn
der triggert, ist die CRT erstmal zufrieden und auch alle benötigten
DLLs wurden geladen. Bisher ist kein eigener Programmcode gelaufen. Dann
halt weiterhangeln. Ist denn dieser HeapValidate()-Aufruf, der in der
ntdll.dll für Unheil sorgt, eigener Code oder ist das DBG-Zeug, welches
VS öffnet, wenn es die Quellen findet?
Heiko schrieb:> Also mal einen Breakpoint direkt an den Anfang von WinMain setzen.
Braucht man nicht, ein "step into" zum Starten des Programmes genügt.
B. P. schrieb:> Harald K. schrieb:>> ein "step into" zum Starten des Programmes genügt>> Gestartet mit F11 Taste. Ergebnis auf dem ScreenShoot.
Wahnsinn, und jetzt scroll mal in der Aufrufliste zu Deiner Funktion -
Doppelclick - und dann kannst du drueber philosophieren wie du das zum
Absturz gebracht hast.
B. P. schrieb:> Und das passiert in einem File debug_heap.cpp von Microsoft.> Ich habe das File nicht in Projekt eingeführt...
Scroll mal in der Aufrufliste ganz runter.
Das was du Zeigst ist das der Code von Microsoft etwas beanstandet was
Deiner verbrochen hat. Und wo das ist findest du in der Aufrufliste.
B. P. schrieb:> debug_heap.cpp
Wie ich oben schon schrieb: Wird der Heap korrumpiert, liegts meist an
einem Überschreiber im Speicher. Der haut nämlich oft Teile der
Verwaltungsinformationen weg.
Ich tippe daher (wie schon in meiner ersten Antwort) auf einen
Buffer-Overflow. Es könnte sich zum Beispiel um ein globales Array
handeln, welches Du in der Größe überschreibst.
Den Stack-Trace, den Du da siehst, ist die Auswirkung, nicht der Fehler.
Der erfolgte bereits früher. Aus meiner Erfahrung kann ich da nur sagen:
Das wird schwierig.
Ein Tipp zur Fehlersuche:
Vergrößere nach und nach jedes globale Array um einen Sicherheitswert,
bis das Programm nicht mehr crasht, also zum Beispiel:
Alt:
1
intmyarray[MY_ARRAY_SIZE];
Neu:
1
intmyarray[MY_ARRAY_SIZE+10000];
Dann bekommst Du vielleicht raus, welches Array da überschrieben wird.
Anschließend suchst Du die Stellen raus, wo das Array beschrieben wird
und bringst die Stellen ggfls. in Ordnung. Anschließend nimmst Du den
zusätzlichen Puffer wieder raus und testest neu. Wenns dann läuft, hast
Du den Fehler gefunden.
Keine Gewähr. Ich schrieb das nur, weil Du sagtest, dass Du at Runtime
keinen Speicher allokierst. Dann muss es ja eine globale Variable sein
oder Du hast Dich mit Deiner Aussage geirrt.
HeapAlloc
Frank M. schrieb:> Wird der Heap korrumpiert, liegts meist an> einem Überschreiber im Speicher.
Für Testzwecke habe ich alle Stelle im Projekt wo ich den Speicher
allokiere entfernt.. Der Fehler bleibt.
Harald K. schrieb:> Heiko schrieb:>> Also mal einen Breakpoint direkt an den Anfang von WinMain setzen.>> Braucht man nicht, ein "step into" zum Starten des Programmes genügt.
Stimmt - hab ich bisher so nie gebraucht. (Sorry, das konnte ich nicht
wissen, denn mein Zeug crasht normalerweise nicht gleich in WinMain...
;))
Ich habe aber trotzdem noch immer keine Antwort auf die Frage, ob das
Progi vom TE überhaupt bis WinMain() kommt.
Heiko schrieb:> Ich habe aber trotzdem noch immer keine Antwort auf die Frage, ob das> Progi vom TE überhaupt bis WinMain() kommt.
Das werden wir wohl auch nie erfahren, da den bereits das Konzept des
Vergrößern eines Fensters und des Scrollens in einer Liste zu
überfordern scheint.
Heiko schrieb:> Der Kollege im Artikel unten hat ein ähnliches Problem> und die gepostete Aufrufsequenz ist praktisch identisch.
Immerhin hat es der Kollege dort geschafft ein ganzer stacktrace zu
posten, der crash dort ist im atexit, vermutlich durch ein terminate
getriggert (nicht gefangene exception?)
Machst du nun im schnellauf alle alten Technologien durch?
Schon möglich dass bloss das inkludieren eines ATL/COM headers was
undefiniertes bewirkt wenn Dein Projekt nicht dafür aufgesetzt ist.
Mmm, der Header ist MBCS-MFC Geraffel. Wenn er das braucht, muß der
Header halt mit rein. Ich würde jetzt ebenfalls einen ganz tiefen Blick
in die Projekt-Einstellungen anregen wollen. Speziell unter dem Punkt
"Zeichensatz".
Trotzdem liegt der Fehler bei Dir.
Eine #include-Anweisung ist kein beim Programmablauf sequentiell
ausgeführter Vorgang, auch wenn Dich das jetzt überraschen mag.
Da Du wohl eine .Net-Anwendung zu, äh, machen scheinst, warum eigentlich
willst Du in der Funktionen wie malloc, VirtualAlloc etc. verwenden?
Wozu nur?
Harald K. schrieb:> Da Du wohl eine .Net-Anwendung zu, äh, machen scheinst, warum eigentlich> willst Du in der Funktionen wie malloc, VirtualAlloc etc. verwenden?
Die Antwort zu der Frage findet sich in den anderen Threads des/der TO.
Er/Sie/Es programmiert nicht in .Net oder C++ oder managed C++, sondern
"in Visual Studio", um eine anscheinend in C++ vorliegende
(Borland-)Anwendung dorthin zu übertragen.
Oliver
Frank M. schrieb:> Vergrößere nach und nach jedes globale Array um einen Sicherheitswert,
Ggf mal mit Valgrind laufen lassen, ode gibts das nicht unter Windows?
Some O. schrieb:> Ggf mal mit Valgrind laufen lassen
Bei den elementaren Problemen, die hier vorliegen, ist das leider
vollkommen sinnlos.
Der Threadstarter kann das Programm im Debugger laufen lassen, scheitert
aber an elementaren Dingen wie der Bedienung des Debuggers (Call Stack
bei auftretender Exception ansehen).
Dazu wird auch krampfhaft gegen die verwendete Programmiersprache (ein
C++-ähnliches Konstrukt für den .Net-Unterbau) gearbeitet, weil gar
nicht verstanden wird, was der Unterschied zu nativem C++ ist, aber ein
natives C++-Programm, das für ein völlig anderes Framework eines anderen
Herstellers geschrieben war, "portiert" werden soll.
Da geht schon lange annähernd alles schief, was schiefgehen kann.
Da hilft Valgrind auch nicht mehr als 'ne homöopathische
Kopfschmerztablette.
Harald K. schrieb:> B. P. schrieb:>> Der Fehler auf Microsoft Seite.>> Nein, das ist er ganz, ganz sicher nicht. Garantiert nicht.
Das erlebe ich oft. Ich fahre mit dem Auto. Daneben sitzt meine
Partnerin. Auf eine Kreuzung, ein Auto (ein Mädchen mit der Nase
auf der Windscheibe…) nimmt mir Vorfahrt.
Meine Partnerin:
1. Vielleicht war sie in Eile...
2. Warum sagst du das? Ich könnte auch als Fahrerin im Auto sein.
...
Jedes Programm hat Potenzial für Fehler. Über vielen Jahren war
dein Programm Weltweit im Einsatz. Nach vielen Jahren bekommst
einen Anruf aus einem weit entfernten Land. Es wird genaue
beschrieben wie und wenn es zu einem Fehler kommt. Einziges Wort
mit dem du reagierst kann ist“Danke“.
Den Microsoft Fehler habe ich schon an Entwickler gemeldet...
B. P. schrieb:> Über vielen Jahren war dein Programm Weltweit im Einsatz.
Dein Programm hier aber nicht.
B. P. schrieb:> Den Microsoft Fehler habe ich schon an Entwickler gemeldet...
Und Dich damit lächerlich gemacht. Jemand, der mit einem Werkzeug nicht
ansatzweise umgehen kann, der die einfachsten Dinge die zur Diagnose
dazugehören, nicht auf die Reihe bekommt, der ausgerechnet will einen
Fehler gefunden haben?
Harald K. schrieb:> Dazu wird auch krampfhaft gegen die verwendete Programmiersprache (ein> C++-ähnliches Konstrukt für den .Net-Unterbau) gearbeitet,
welches denn genau? ATL hat nichts mit .Net zu tun, die Verwendung mit
MFC ist erlaubt.
Für einen Fehlerbericht ist aber ein Minimalbeispiel nötig, also z.B.
das aus der Doku:
https://learn.microsoft.com/de-de/cpp/atl-mfc-shared/using-cstring?view=msvc-170&source=recommendations
Wenn das den Fehler zeigt, dann könnte man das melden.
Ich würde aber eher vermuten das irgendwelche
Compiler/Linkereinstellungen für die Verwendung von ATL nicht richtig
eingestellt sind. Wenn der Compiler nicht meckert, dann wird ja auch
keine ATL Funktion verwendet.
Trotzdem sollte über ein Redesign mit managed Code in C++ oder gleich C#
nachgedacht werden. Die wilden Zeigerorgien sind viel zu gefährlich und
schon lange überflüssig.
B. P. schrieb:> Und das ist das Minimalbeispiel.
Und welche Compiler-/Projekteinstellungen? Welche Sprache benutzt Du
überhaupt, hast Du das schon herausgefunden?
Damit bekomme ich keine Fehler mit aktuellem VS2019,
Kommandozeilenprojekt mit atlstr.h und auch der CString Klasse aus dem
Beispiel. Auch mit /clr Option geht es.
gut, das VS2022 muss ich sowieso noch installieren, dann teste ich es
damit auch mal.
getan, mit frisch installiertem VS2022 läuft es immer noch. Das unter
VS2019 angelegte Projekt geöffnet, Plattformtoolset wurde von v142 auf
v143 aktualisiert, kompiliert, läuft.
In Debug/Release, mit und ohne /clr.
Vielleicht mal dein Minimalprojekt hier posten, dann kann man sehen ob
es Installationsabhängig ist.
ich kann das Problem nur bestätigen, mit Toolset v142 funktioniert es
und mit v143 nicht. Geändert wurde da etwas am CAtlStringMgr, damit
scheint es zusammenzuhängen. Im neueren Code crasht es wenn eine
Funktion für das Programm beenden hinzugefügt werden soll, da gibt es
keinen Speicher für die Liste der Funktionen.
Auch die Forms Includes habe ich rausgeworfen, es scheint wirklich am
User Code zu liegen. Ich sehe nur nicht viel Unterschied zu meinem Test,
kann jetzt aber gerade nicht mehr weitersuchen.
J. S. schrieb:> Vielleicht mal dein Minimalprojekt hier posten, dann kann man sehen ob> es Installationsabhängig ist.
Alles was im Minimalprojekt ist wurde von Visual Studio
generiert außer eingefügten #include <atlstr.h>. Das
Mininimalprojekt habe ich an Microsoft Entwickler weiter geleitet.
Hier die Korrigierte variante wo du nun dein ATL header inkludieren
kannst.
Das Problem ist dass du den Einstiegspunkt in die Applikation verbogen
hast, womit die CRT initialisiertung umgangen wurde. Das hat einen
Einfluss auf atexit(), welches von dem ATL code aufgerufen wird.
Extra gratis Tip: Wenn du Deine Projekte postetst, dann entferne die
binaries und .vs Ordner, 38MB fuer nix.
Roger S. schrieb:> Das Problem ist dass du den Einstiegspunkt in die Applikation verbogen> hast, womit die CRT initialisiertung umgangen wurde.
Das ist ja ein Ding. Also doch ein Fehler im Programm und kein Fehler
von Microsoft.
Das kommt jetzt völlig überraschend.
Merksatz: Wenn man einen Fehler im Compiler vermutet, dann liegt der
Fehler praktisch immer im eigenen Programm. Compilerfehler kommen extrem
selten vor. Fehler im eigenen Programm kommen hingegen ständig vor.
Einfachste Wahrscheinlichkeitsrechnung.
MaWin O. schrieb:> Das ist ja ein Ding. Also doch ein Fehler im Programm und kein Fehler> von Microsoft.
Alles was im Minimalprojekt ist wurde von Visual Studio
generiert außer eingefügten #include <atlstr.h>.
Und mit älteren Versionen (vor dem update...) läuft das
fehlerfrei.
B. P. schrieb:> Alles was im Minimalprojekt ist wurde von Visual Studio> generiert
Ach ja?
Roger S. schrieb:> Das Problem ist dass du den Einstiegspunkt in die Applikation verbogen> hast,
Harald K. schrieb:> B. P. schrieb:>> Alles was im Minimalprojekt ist wurde von Visual Studio>> generiert>> Ach ja?
Fairer Weise muss man sagen, dass es wohl vom Projekt Template so
aufgesetzt wurde. Aber dennoch sollte man sich ein wenig mit der Materie
auseinandersetzen, erst recht, wenn man den Schwierigkeitsgrad anhebt
indem man Technologien einsetzt die für fortgeschrittene Spieler gedacht
sind.
Roger S. schrieb:> Fairer Weise muss man sagen, dass es wohl vom Projekt Template so> aufgesetzt wurde.
So ist das halt. Ein Template kann eben nicht für jeden Einsatzzweck
vorbereitet sein. Da muss sich der Entwickler selbst drum kümmern.
Und dass es mit einer alten Version funktioniert hat, ist ja purer
Zufall. Der Fehler ist und bleibt beim Projektentwickler.
MaWin O. schrieb:> Und dass es mit einer alten Version funktioniert hat, ist ja purer> Zufall. Der Fehler ist und bleibt beim Projektentwickler.
Ja, eindeutig.
ATL und CLR ist aber genauso in MS Beispielcode zu finden. Das es vorher
funktioniert hat und nachdem MS etwas an der globalen CAtlStringMgr
Instanz geändert hat, kann es genauso gut sein das MS da nicht alles
bedacht hat.
Frank M. schrieb:> Hier wurden schon viele Threads aufgemacht mit sehr vielen angeblichen> Compilerfehlern, die zum Beispiel dem gcc angedichtet wurden. Wie sich> am Ende zu 99,5% herausgestellt hat, war nicht der Compiler schuld,> sondern der Programmierer.
+1
aber neue Versionen sind ja auch nie fehlerfrei und bringen neue bis
jetzt unentdeckte Fehler mit.