Forum: PC-Programmierung [C] Programm hängt sich beim Aufruf von malloc() auf


von genervter Programmierer (Gast)


Lesenswert?

Hallo,

ich hab hier ein Programm/Problem was mir zur Weißglut bringt!

OS: XP SP3
IDE: Code::Blocks 8.02
  Compiler: MinGW, "gcc.exe -v" sagt "version 3.4.5 (mingw-vista 
special)"
  Debugger: GNU gdb 6.7.50.20071127

Ich versuch mal das Ganze möglichst kurz und komplett zu erklären: Ich 
hab hier ein halbfertiges Programm welches Datensätze von einem Format 
in ein anderes konvertieren soll. Ein-/Ausgabe soll über Textdateien 
laufen, Eingabe funktioniert auch prima, der Lesepuffer ist mit 1500 
Bytes etwas überdimensioniert, Ausgabe fehlt noch. Da die Datensätze 
unterschiedliche Längen haben und es mal mehr mal weniger sind wird 
massiv Gebrauch von malloc(), realloc() und memcpy() gemacht, 
Datenmengen jeweils einige zehn bis hundert Bytes(!). Den Code darf ich 
leider nicht veröffentlichen, außerdem ist er ziemlich lang und ein 
"funktionierendes" (d.h. den selben Fehler produzierendes) 
Minimalbeispiel krieg ich nicht hin. Das ganze compiliert mit "-Wall" 
ohne eine einzige Warnung.

Problem: Das Programm konvertiert ein paar Datensätze, hängt sich dann 
für ein paar Sekunden oder Minuten auf und beendet sich mit irgendeinem 
Rückgabewert ungleich Null (welcher im Programm nirgendswo verwendet 
wird). Das ganze ist halb reproduzierbar, d.h. es tritt immer an der 
gleichen Stelle im Programmablauf, zu 99,9% ein malloc-Aufruf(!), und 
mit dem gleichen Rückgabewert auf, bis das Programm leicht verändert 
wird. Über Code::Blocks (Taste F9) gestartet konvertiert es aktuell 7 
Datensätze und gibt dann augenblicklich -1073741819 (0xC0000005) zurück, 
direkt im Explorer gestartet konvertiert es 126 Sätze und beendet sich 
dann ohne jegliche Fehlermeldung. Gestern, bevor ich einen Fehler 
entfernt und weitere Debugausgaben eingebaut hatte gab es jedesmal ~30 
Sekunden Wartezeit bis zum Programmabsturz.

Ich habe ein paar Testvariablen eingebaut, malloc und memcpy werden fast 
1000 mal aufgerufen, realloc ungefähr 150 mal. Die Rückgabewerte der 
drei Funktionen werden geprüft und entsprechend reagiert. Der ganze Code 
macht massiven Gebrauch von Strukturen und Pointern (und Pointern in 
Strukturen).

Ich tippe auf irgendein Pointerproblem, finde die Stelle aber zum 
verrecken nicht. Wenn irgendwo ein Pointer Amok läuft kommt meistens 
eine Meldung das Programm hätte "ein Problem festgestellt" usw., hier 
kommt keine solche Meldung. Außerdem würde sich das Programm dann wohl 
eher bei memcpy erhängen, nicht beim Aufruf von malloc.

Wenn ich das Programm im Debugger laufen lasse gibt es nach aktuell 29 
Datensätzen das da:
1
Program received signal SIGTRAP, Trace/breakpoint trap.
2
In ntdll!DbgUiConnectToDbg () (C:\WINDOWS\system32\ntdll.dll)
Laut Google ist also ein Ereignis eingetreten über welches GDB 
informiert werden will. Schön, aber WELCHES Ereignis? Und in welcher 
Zeile vom Programm? Breakpoints gibts keine, wenn ich Pointer und Memory 
manuell beobachte kann ich keinen Fehler finden (bzw. habe einen 
falschen Index gefunden und korrigiert, aber das Problem bleibt). Leider 
kann man nur 256 Bytes Speicher auf einen Schlag anzeigen, das macht die 
Sache nicht einfacher.

Ich hab einen bestimmten memcpy-Aufruf im Verdacht, wenn ich diesen 
entferne funktionert alles (natürlich mit falschen Ergebnissen). Ich hab 
den Aufruf jetzt zig mal geprüft und genaustens im Debugger observiert, 
da passt alles! Ich vermute also das Problem ist woanders.

Den Präprozessor anzuweisen memcpy durch memmove zu ersetzen 
(überlappende Speicherbereiche) hat auch nichts gebracht.

rhhhhaaaaa!!! Ich sitz jetzt 2 Tage an dem Mist und hab echt die Nase 
voll so kurz vor Weihnachten.

Was ist da los? Ich weiss ohne Code ists schwer, aber vielleicht hat ja 
jemand eine Idee. Gibt eine Möglichkeit dem Debugger zu entlocken was 
genau sich hinter dem SIGTRAP versteckt? Was mir aufgefallen ist: 
realloc weist meistens (immer?) einen neuen Speicherbereich zu, die neue 
Adresse ist dabei stehts höher als die alte. Kann es sein dass dem 
Programm schlicht der Speicher ausgeht? (Bei ein paar hundert 
angeforderten Bytes???). Wo wird überhaupt die Info gespeichert wieviel 
Bytes jetzt an Adresse 0xabc reserviert worden sind?

Weihnachtliche Grüße!

von 900ss (900ss)


Lesenswert?

genervter Programmierer schrieb:
> malloc(), realloc() und memcpy()

Wenn du niemals free() benutzt, dann wird dir wohl irgendwann der 
Speicher ausgehen. Überprüfst du den Rückgabewert von malloc()? Wenn 
kein Speicher mehr da ist, dann gibt malloc() 0 zurück. Wenn du das 
nicht abfängst, dann kennst du jetzt dein Problem.

Außerdem könntest du einen statischen Buffer nutzen. Er sollte dann so 
lang sein, wie dein längster Datensatz, der vorkommen kann.

von Karl H. (kbuchegg)


Lesenswert?

Die wahrscheinlichste Variante ist es, dass irgendwo der allokierte 
Speicher massiv überlaufen wird, also beispielsweise 100 Bytes allokiert 
wurden und dann ab Beginn dieses Pointer 140 Bytes reingeschrieben 
werden. Dadurch sind die Chancen recht groß, dass man die Steuerinfo, 
die sich malloc zwischen die Datenblöcke legt, niederbügelt und dadurch 
die ganze Speicherverwaltung zerschossen wird.
Alles was dann danach passiert ist nur noch Formsache.

von R. F. (rfr)


Lesenswert?

Dein Problem scheint mir der Speicher zu sein. Wenn du keinen Code 
posten kannst, poste doch mal <eine Speicherbelegung.

Gruss
Robert

von Karl H. (kbuchegg)


Lesenswert?

Da

> Ausgabe fehlt noch. Da die Datensätze
> unterschiedliche Längen haben und es mal mehr mal weniger sind wird
> massiv Gebrauch von malloc(), realloc() und memcpy() gemacht,
> Datenmengen jeweils einige zehn bis hundert Bytes(!).

hat sich wer massenhaft Arbeit für nichts gemacht.

100 Bytes sind doch auf einem PC kein Thema.

Einfach alle möglichen Datensätze beschreiben. Jeder mit seiner eigenen 
Struktur, alle mittels einer Union überinanderlegen, noch ein Typflag 
dazu und schon ist das alles kein Thema mehr.
Und schneller gehts auch
Und weniger Speicher wirds wahrscheinlich auch brauchen.

von genervter Programmierer (Gast)


Lesenswert?

Schon mal Danke für die schnellen Reaktionen!

900ss D. schrieb:
> genervter Programmierer schrieb:
>> malloc(), realloc() und memcpy()
>
> Wenn du niemals free() benutzt, dann wird dir wohl irgendwann der
> Speicher ausgehen.
Insgesamt dürften da wohl keine 2MB verwendet werden, würde mich 
wundern...

> Überprüfst du den Rückgabewert von malloc()? Wenn
> kein Speicher mehr da ist, dann gibt malloc() 0 zurück. Wenn du das
> nicht abfängst, dann kennst du jetzt dein Problem.
Rückgabewerte von malloc, memcpy und realloc werden überprüft, bei einem 
Fehler gibts eine Meldung und exit(EXIT_FAILURE). :-)

Karl heinz Buchegger schrieb:
> Dadurch sind die Chancen recht groß, dass man die Steuerinfo,
> die sich malloc zwischen die Datenblöcke legt, niederbügelt und dadurch
> die ganze Speicherverwaltung zerschossen wird.
Das ist eine gute Info! Die Speicherverwaltung liegt zwischen den 
Datenblöcken, das ist allerdings sehr fehleranfällig.

Gibt es nicht eine Methode den Debugger anzuweisen die Speicherbereiche 
auf "Grenzüberschreitungen" zu überwachen oder einfach die ganzen 
Speicheroperationen zu protokollieren und/oder irgendwie sinnvoll 
(d.h. brauchbar) darzustellen? Mit max. 256 Bytes die ich mir anzeigen 
lassen kann komme ich hier nicht weit!

R. Freitag schrieb:
> Dein Problem scheint mir der Speicher zu sein. Wenn du keinen Code
> posten kannst, poste doch mal <eine Speicherbelegung.
Was genau verstehst du unter "Speicherbelegung"? In welcher Form bzw. 
mit welchem Tool/... erzeugt?

Ich werd in der Zwischenzeit mal die memcpy()-Aufrufe genau unter die 
Lupe nehmen und testweise immer etwas mehr Speicher reservieren.

Karl heinz Buchegger schrieb:
> Da
>
>> Ausgabe fehlt noch. Da die Datensätze
>> unterschiedliche Längen haben und es mal mehr mal weniger sind wird
>> massiv Gebrauch von malloc(), realloc() und memcpy() gemacht,
>> Datenmengen jeweils einige zehn bis hundert Bytes(!).
>
> hat sich wer massenhaft Arbeit für nichts gemacht.
Das ist gut möglich... Die Daten sind aktuell in Textform und sollen in 
ein "Binärformat" (nicht vernünftig im Editor darstellbar) konvertiert 
werden. Strings die mehrfach vorkommen werden dabei über Indexes 
angesprochen usw., sehr fehleranfällig. Ich werd mal gucken ob bzw. in 
wie weit ich die Sache vereinfachen kann, union ist ein gutes Stichwort.

von R. F. (rfr)


Lesenswert?

<Was genau verstehst du unter "Speicherbelegung"? In welcher Form bzw.
<mit welchem Tool/... erzeugt?

Unter Speicherbelegung verstehe ich die Belegung des Arbeitsspeichers. 
:-)

( vortreffliches Amusement, hier...)

Wer per malloc Speicher alloziiiert, bekommt einen Zeiger zurück, zB so:
int *ptr = malloc(10 * sizeof (int));

Vom Zeiger ausgehend bis zum Ende von 10 * sizeof(int) ist der Speicher 
belegt.

Was ich vermute, ist, dass sich das Malloc in Zusammenarbeit mit den OS 
verheddert, und mit einer Speicherbelegung findest du heraus, wo.

Das bedeutet abewr nicht, dass du dann eine Lösung hast.

Gruss
Robert

von genervter Programmierer (Gast)


Lesenswert?

R. Freitag schrieb:
> <Was genau verstehst du unter "Speicherbelegung"? In welcher Form bzw.
> <mit welchem Tool/... erzeugt?
>
> Unter Speicherbelegung verstehe ich die Belegung des Arbeitsspeichers.
> :-)
Soooo doof bin ich auch wieder nicht. ;-)
Mal ernsthaft: Soll ich alle Pointer notieren oder was genau? Wenn man 
dir die Aufgabe "Speicherbelegung erzeugen/zeigen" stellt, wie würdest 
du das machen bzw was würdest du machen? Ich meine ich kann alle 
Adressen (bzw. "Pointerwerte") notieren, aber das bringt mir ja nicht 
wirklich viel (ist bei ~1000 malloc-Aufrufen aber eine Menge Arbeit). 
Irgendwie bin ich wohl schwer von Begriff heute.

Wirklich interessant sind wohl die "Grenzüberschreitungen", aber die 
muss man erstmal finden! Es muss doch eine Möglichkeit geben das den 
Debugger oder irgendein anderes Tool machen zu lassen.

(Zitat von oben)
Gibt es nicht eine Methode den Debugger anzuweisen die Speicherbereiche
auf "Grenzüberschreitungen" zu überwachen oder einfach die ganzen
Speicheroperationen zu protokollieren und/oder irgendwie sinnvoll
(d.h. brauchbar) darzustellen? Mit max. 256 Bytes die ich mir anzeigen
lassen kann komme ich hier nicht weit!

von Karl H. (kbuchegg)


Lesenswert?

genervter Programmierer schrieb:
> Schon mal Danke für die schnellen Reaktionen!
>
> 900ss D. schrieb:
>> genervter Programmierer schrieb:
>>> malloc(), realloc() und memcpy()
>>
>> Wenn du niemals free() benutzt, dann wird dir wohl irgendwann der
>> Speicher ausgehen.
> Insgesamt dürften da wohl keine 2MB verwendet werden, würde mich
> wundern...


Wird jetzt ge-freed() oder nicht?

Wenn nicht, dann such dir einen Fetzen (ein schweres Stück Tuch), mach 
es nass und drisch es dem Original-Programmierer solange um die Ohren, 
bis du nur noch gaaaanz kleine Stoffstückchen in der Hand hältst. Dazu 
murmelst du die Worte: Du sollst allokierten Speicher auch wieder 
freigeben, du sollst allokierten Speicher wieder freigeben.

Alternativ kannst du auch ein Badetuch nehmen.


Im Ernst: Wenn free() drinnen wären, hätte man eine kleine 
Speicherüberwachung mit Guard-Bytes machen können. In vielen Fällen 
kommt man so den Übeltätern schnell auf die Schliche.

Aber wer eben schlampig programmiert, muss mit den Konsequenzen leben 
können. Man räumt Speicher hinter sich IMMER auf! Alles andere ist 
Murks.

von R. F. (rfr)


Lesenswert?

Gips!!

Electric Fence helps you detect two common programming bugs: software 
that overruns the boundaries of a malloc() memory allocation, and 
software that touches a memory allocation that has been released by 
free(). Unlike other malloc() debuggers, Electric Fence will detect read 
accesses as well as writes, and it will pinpoint the exact instruction 
that causes an error. It has been in use at Pixar since 1987, and at 
many other sites for years.

Electric Fence uses the virtual memory hardware of your computer to 
place an inaccessible memory page immediately after (or before, at the 
user's option) each memory allocation. When software reads or writes 
this inaccessible page, the hardware issues a segmentation fault, 
stopping the program at the offending instruction. It is then trivial to 
find the erroneous statement using your favorite debugger. In a similar 
manner, memory that has been released by free() is made inaccessible, 
and any code that touches it will get a segmentation fault.

Simply linking your application with libefence.a will allow you to 
detect most, but not all, malloc buffer overruns and accesses of free 
memory. If you want to be reasonably sure that you've found all bugs of 
this type, you'll have to read and understand the rest of this man page.

aus: http://linux.die.net/man/3/efence kopiert.

von Nico S. (Gast)


Lesenswert?

Valgrind kann das auch.

von genervter Programmierer (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> genervter Programmierer schrieb:
>> Schon mal Danke für die schnellen Reaktionen!
>>
>> 900ss D. schrieb:
>>> genervter Programmierer schrieb:
>>>> malloc(), realloc() und memcpy()
>>>
>>> Wenn du niemals free() benutzt, dann wird dir wohl irgendwann der
>>> Speicher ausgehen.
>> Insgesamt dürften da wohl keine 2MB verwendet werden, würde mich
>> wundern...
>
>
> Wird jetzt ge-freed() oder nicht?
Ich kann keinen free-Aufruf finden... Allerdings ist das Programm wie 
gesagt halbfertig (eher "viertelfertig") und der bisher reservierte 
Speicher wird auch bis zum (aktuellen) Programmende gebraucht. Wenn das 
Programm beendet wird dürfte der Speicher doch automatisch freigegeben 
werden oder?

(Falls nicht: Das Problem dürfte trotzdem woanders liegen, der Fehler 
tritt auch beim ersten Aufrufen des Programmes nach dem Start des 
Computers auf.)

Ich hasse es fremden Code debuggen zu müssen...

R. Freitag schrieb:
> Gips!!
Wie bitte?

> Electric Fence helps you detect two common programming bugs: [...]
Das klingt prima, guck ich mir morgen an! Aber... ist das nicht 
(ausschließlich) für Linux?

von Frank Morster (Gast)


Lesenswert?

Das Aufräumen läßt man dem Garbage-Collector. :-)

Oder halt dem Betrübssystem beim Beenden des Programms.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Würdest Du einen halbwegs aktuellen Microsoft-Compiler (wie z.b. das 
kostenfreie Visual C++ Express) verwenden, könntest Du die erweiterten 
C-Runtime-Checks der damit gelieferten Debugruntime-Library nutzen - und 
den integrierten Debugger, der GDB hier wohl ein bisschen überlegen ist.

Mir ist klar, daß das kein wirklich hilfreicher Hinweis ist, aber 
andererseits könntest Du mit noch vertretbarem Aufwand das einfach mal 
ausprobieren.

von genervter Programmierer (Gast)


Lesenswert?

Rufus Τ. Firefly schrieb:
> Würdest Du einen halbwegs aktuellen Microsoft-Compiler (wie z.b. das
> kostenfreie Visual C++ Express) verwenden, könntest Du die erweiterten
> C-Runtime-Checks der damit gelieferten Debugruntime-Library nutzen - und
> den integrierten Debugger, der GDB hier wohl ein bisschen überlegen ist.

Darf ich diesem Post entnehmen dass es in GDB keine Möglichkeit gibt die 
Bereichsgrenzen der mit malloc() angeforderten Speicherblöcke zu 
überwachen?

Ist es nicht zumindestens möglich größere Speicherblöcke auszulesen und 
anzuzeigen? 256 Bytes sind etwas wenig, wenn ich ein paar kB auf einmal 
betrachten könnte würde das schon helfen.

Ich meine mich zu erinnern dass dieses Visual-Gewusel sehr langwierig zu 
installieren ist und viel Platz braucht, naja... Wenn es keine andere 
Möglichkeit gibt werd ich es wohl probieren (müssen). Wobei man sich in 
die Programme ja auch erstmal einarbeiten muss...

Nico S. schrieb:
> Valgrind kann das auch.
Das läuft laut Wiki auch nicht unter Windows. :-(

Mal sehen ob ich morgen weitermache oder erst nach Weihnachten.

von genervter Programmierer (Gast)


Lesenswert?

genervter Programmierer schrieb:
> Ich werd in der Zwischenzeit mal die memcpy()-Aufrufe genau unter die
> Lupe nehmen und testweise immer etwas mehr Speicher reservieren.

Der Präprozessor ist schon eine verdammt praktische Erfindung: Eine 
Zeile an den Anfang
1
#define malloc(a) malloc(2*(a))
und das Programm läuft ohne Absturz durch. :-) Das bestätigt die 
wahrscheinlichste Theorie (Bereichsüberschreitung), jetzt muss ich "nur" 
noch den Fehler finden...

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

genervter Programmierer schrieb:
> Darf ich diesem Post entnehmen dass es in GDB keine Möglichkeit gibt die
> Bereichsgrenzen der mit malloc() angeforderten Speicherblöcke zu
> überwachen?

Das weiß ich nicht -- ich nutze GDB nicht, und erst recht nicht für das 
Debuggen von Windows-Anwendungen. Nur weiß ich, daß die Debug-CRT des VC 
etliche aktivierbare "runtime checks" bietet, die auch einen 
zerschriebenen Heap erkennen können.
Auch vermag der VC-Debugger von Haus aus sinnvoller mit so einer 
Situation umzugehen:
> Program received signal SIGTRAP, Trace/breakpoint trap.
> In ntdll!DbgUiConnectToDbg () (C:\WINDOWS\system32\ntdll.dll)

Ich will nicht ausschließen, daß man GDB auch beibringen kann, in so 
einem Fall an die die Exception auslösende Codestelle zu springen, der 
MS-Debugger macht das jedoch von vorn herein richtig. Übrigens auch, 
wenn man den Debug-Build außerhalb des Debuggers startet, dann kann der 
auch nachträglich bei Programmabsturz aktiviert werden.

von genervter Programmierer (Gast)


Lesenswert?

Kurze Frage zum Visual Studio Express:

Bei MS steht für die Version 2010
1
we do require that you register your product within 30 days of 
2
installation for continued use.

und für die Version 2008
1
Register your product within 30 days from installation.

Ich interpretiere dass als "2010 muss registriert werden, 2008 kann." 
Ist das richtig? Gibt es eine Möglichkeit die Registrierung nicht 
direkt per Internet durchzuführen (und dabei jede Menge Daten 
preiszugeben)?

Rufus Τ. Firefly schrieb "halbwegs aktuell", trifft das auf die 
2008-Version zu?

Ich lade momentan beide ISOs runter.

Nochmals Danke für die Hilfe!

von Karl H. (kbuchegg)


Lesenswert?

Guard Bytes in der Debug Version macht der MS Compiler seit Anbeginn der 
Windows Welt.

Allerdings weiß ich nicht, ob die dir hier was bringen werden, wenn 
nichts gefreed wird. Denn beim Freigeben von Speicher, wird nachgesehen, 
ob die Guard Bytes noch intakt sind. Wird nichts freigegeben gibts auch 
keine Überprüfung.

Aber man kann den Memory Check irgendwie auch manuell anwerfen. Mal 
danach googeln.


Edit:
Während du den Download machst, google mal ein bischen.
Mit "VC++ guard bytes"
findet sich vieles.

von genervter Programmierer (Gast)


Angehängte Dateien:

Lesenswert?

Das geht ja gut los! ISO geladen, DVD(-RW) gebrannt, Setup gestartet, 
erste von acht Komponenten wird installiert, BUMM. Vielleicht sollte MS 
mal seinen eigenen Installer debuggen...

Und jetzt?

Ich merk schon das wird wieder lustig. :-(

von Lukas K. (carrotindustries)


Lesenswert?

genervter Programmierer schrieb:
> Und jetzt?

Prüfsummen der ISOs überprüfen.

von Peter (Gast)


Lesenswert?

kann es sein das du kein .net auf den PC hast? So in der Art sieht es 
auch aus wenn man ein .NET programm ohne Runtime startet.

von genervter Programmierer (Gast)


Lesenswert?

Luk4s K. schrieb:
> genervter Programmierer schrieb:
>> Und jetzt?
>
> Prüfsummen der ISOs überprüfen.
Die kann ich bei MS nicht finden... Ich werd die ISO nochmal laden, 
leider liefert der MS-Server die Dateien zur Zeit nur häppchenweise. 
Aktuell 80kB/s, meine Verbindung schafft locker das 8-fache. grrr

Peter schrieb:
> kann es sein das du kein .net auf den PC hast? So in der Art sieht es
> auch aus wenn man ein .NET programm ohne Runtime startet.
Ich habe .NET 2 SP2 , .NET 3 SP2 und .NET 3.5 SP1 installiert, dazu 
"VC++ irgendwas Redistributables". Letzere hab ich entfernt, ging 
problemlos. .NET 3.5 wollte ich versuchsweise auch mal deinstallieren 
-->BUMM. Also von MS ein Tool gezogen um den Kram "manuell" zu 
entfernen, geht auch nicht, MS Installer spinnt. Letzteren nach 
Anleitung [1] "repariert", Version 4.5 installiert, .NET 3.5 mittels 
MS-Tool erfolgreich entfernt,  Installation vom Express Studio nochmal 
gestartet, Punkt 1 von 9(!) = Installation irgendwelcher 
Redistributables --> BUMM.

Sch***! Jetzt sitz ich schon wieder 1,5h und hab nicht mal Visual Studio 
installiert. seufz

Hat jemand eine Ahnung was da los ist?

[1] 
http://www.ehow.com/how_4842153_repair-windows-xp-installer-free.html

von genervter Programmierer (Gast)


Lesenswert?

Ich hab den Download abgebrochen, 1,5h will ich nicht warten. Wenn es 
dem Server besser geht (heute Nacht?) versuch ich mal dieses [1] ISO 
runterzuladen, das ist gleich 3GB groß aber funktioniert vielleicht 
besser. Hat jemand eine Ahnung wo genau der Unterschied zu der Datei von 
[2] liegt?

[1] 
http://www.microsoft.com/downloads/details.aspx?FamilyID=94DE806B-E1A1-4282-ABC5-1F7347782553&displayLang=de
[2] http://www.microsoft.com/express/Downloads/#2008-All

von Peter (Gast)


Lesenswert?

genervter Programmierer schrieb:
> Hat jemand eine Ahnung wo genau der Unterschied zu der Datei von liegt?
nein, aber nicht nicht die Deutsche Version. Sie haben sie haben dort 
auch die Compiler meldungen übersetzt.
Danach hast du es mit
    schlechten Zeigern
und änlichen dinge zu tun. Wo man jedes mal erst übersetzen muss um mit 
dem Fehler etwas anzufangen.

von genervter Programmierer (Gast)


Lesenswert?

Ist ja alles sehr merkwürdig. Es gibt eine englische Version mit 749MB, 
eine deutsche mit ~800MB und eine deutsche mit ~3GB. Aber es gibt keine 
englische Version mit 3GB.

???

Ich bastel dann mal weiter. :-(

von besucher (Gast)


Lesenswert?

Mal zurück zum ursprünglichen Problem.

Es kracht bei Malloc. Die Ursache ist wahrscheinlich ein zu großes 
Memcopy. Dein Problem ist, dass du viele Aufrufe von memcpy hast und 
nicht nachverfolgen kannst, welcher der böse ist. Richtig?

Dabei ist die Aufgabe doch eigentlich einfach: Textdatei lesen, Daten 
interpretieren und irgendwas damit anfangen. Wie kann da ein derart 
kompliziertes und unwartbares Programm herauskommen?

Meine Meinung: Da ist irgendwo ein gewaltiger Wurm drin. Schmeiß den 
Code weg und fang neu an, und strukturier es so, dass du den Überblick 
behältst:

Datensatz einlesen
Erkennen, um welche Art Datensatz es sich handelt
Datensatz auswerten - hier wird unter Umständen gemalloct und gememcpyt.
Auswertung zur weiteren Verarbeitung irgendwo hinschieben (erst mal nur 
printf'en)
Wichtig: Aufräumen, nicht mehr gebrauchten Speicher zurückgeben!
Von oben für den nächsten Datensatz.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

genervter Programmierer schrieb:
> Kurze Frage zum Visual Studio Express:
>
> (...)
>
> Ich interpretiere dass als "2010 muss registriert werden, 2008 kann."
> Ist das richtig?

Vermag ich nicht zu beurteilen, ich nutze die mit meinem Firmen-MSDN-Abo 
kommende nicht-Express-Version, da ich ein größeres Gemenge an 
MFC-Anwendungen pflegen muss.

> Rufus Τ. Firefly schrieb "halbwegs aktuell", trifft das auf die
> 2008-Version zu?

Ja. VC++ 6 war diesbezüglich noch etwas dürftig, alles neuere (am besten 
ab 2005) reicht hierfür.

> Nochmals Danke für die Hilfe!

Naja, nach dem, was ich hier so von den Download- und 
Installationsproblemen lesen, hätte ich Verständnis dafür, wenn der 
etwas abgeklungen sein könnte ...

Ärgerlich ist, daß es diesen Compiler nicht ohne all das .Net-Geraffel 
gibt, und vermutlich macht das auch die meisten Probleme. Der C- und 
C++-Compiler für "nativen" Code (also nicht das .Net-Geraffel) ist 
hingegen wie auch der Debugger vorzüglich.

von Peter (Gast)


Lesenswert?

Rufus Τ. Firefly schrieb:
> Ärgerlich ist, daß es diesen Compiler nicht ohne all das .Net-Geraffel
> gibt, und vermutlich macht das auch die meisten Probleme.

mann muss nur richtig suchen, das Platform SDK enthält den compiler der 
sogar 64bit code erzeugen kann.

Aber dort ist das Studio nicht dabei, um das geht es ja hier.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Um das Studio selbst auch nicht, sondern primär um den integrierten 
Debugger. Mit dem Windbeutel* will man aus gutem Grund nicht arbeiten, 
der ist ... fast bäh.

*) Windbg

von genervter Programmierer (Gast)


Lesenswert?

Jetzt bin ich definitiv reif fürs Irrenhaus.

Aber mal langsam.

besucher schrieb:
> Es kracht bei Malloc. Die Ursache ist wahrscheinlich ein zu großes
> Memcopy. Dein Problem ist, dass du viele Aufrufe von memcpy hast und
> nicht nachverfolgen kannst, welcher der böse ist. Richtig?
Ja.

> Dabei ist die Aufgabe doch eigentlich einfach: Textdatei lesen, Daten
> interpretieren und irgendwas damit anfangen. Wie kann da ein derart
> kompliziertes und unwartbares Programm herauskommen?
42. (keine Ahnung)

> Meine Meinung: Da ist irgendwo ein gewaltiger Wurm drin. Schmeiß den
> Code weg und fang neu an, und strukturier es so, dass du den Überblick
> behältst:
Zeitlich gesehen natürlich das einzig Sinnvolle, aber irgendwann packt 
es einen und mal will den Fehler unbedingt finden...

Weiter im Text:

Visual Studio Express Dingsda wollte nicht, also Wikipedia nach "Guard 
Byte" [1] gefragt (wie von Karl heinz Buchegger am 22.12.2010 um 20:18 
Uhr erwähnt), mittels Präprozessor die malloc-, realloc- und 
memcpy-Aufrufe umgebogen und versucht ein paar "Wächterbytes" 
einzubauen. Hat auch mehr oder weniger funktioniert, allerdings waren 
die gemeldeten Fehler im Debugger nicht nachzuvollziehen bzw. vorhanden.

Also den nächsten Anlauf gestartet den MS-Krempel zu installieren. 
Nachdem ich zig Einstellungen geändert habe (v.a. Dienste), ein paar mal 
".NET Cleanup Tool" ausgeführt und bestimmt 3 mal den Windows Installer 
neu installiert habe ist die Installation der englischen Version von 
2008 ohne Probleme durchgelaufen, interessanterweise wurden nur 5 statt 
9 Komponenten installiert. So weit so gut, ich darf nur nicht daran 
denken was ich alles verändert habe ohne mir Notizen zu machen und wie 
viele potentielle neue Probleme ich dabei erzeugt habe.

Nachdem ich stdint.h und inttypes.h nachträglich eingebaut habe (sind 
nicht im Lieferumfang der 2008er-Version, s. engl. Wikipedia), die 
Sprache auf "C" umgestellt und einige __attribute ((_packed_)) aus 
einem Headerfile entfernt habe hat das ganze mit ein paar Warnungen 
(geprüft, harmlos) tatsächlich kompiliert. Und ob ihr es glaubt oder 
nicht, die mit V-Studio erzeugte Version läuft komplett ohne Fehler 
durch.

Das hat mich etwas misstrauisch gemacht und ich habe mal das Headerfile 
genau unter die Lupe genommen.

Aktueller Stand:
So
1
typedef struct
2
{
3
  uint8_t xxx;
4
  union
5
  {
6
    uint16_t yyy;
7
    uint16_t zzz;
8
  };
9
} xyz_t;
läuft das Programm (mit GCC kompiliert) komplett durch, so
1
typedef struct __attribute__ ((__packed__))
2
{
3
  uint8_t xxx;
4
  union
5
  {
6
    uint16_t yyy;
7
    uint16_t zzz;
8
  };
9
} xyz_t;
,so
1
typedef struct
2
{
3
  uint8_t xxx;
4
  union  __attribute__ ((__packed__))
5
  {
6
    uint16_t yyy;
7
    uint16_t zzz;
8
  };
9
} xyz_t;
oder so
1
typedef struct  __attribute__ ((__packed__))
2
{
3
  uint8_t xxx;
4
  union  __attribute__ ((__packed__))
5
  {
6
    uint16_t yyy;
7
    uint16_t zzz;
8
  };
9
} xyz_t;
läuft es NICHT.

WHAAAAAAA!!! Kann mir mal jemand erklären was da los ist? Ich suche mir 
3 Tage einen Wolf und dann ist so ein dämliches Compilerattribut schuld? 
Das kann doch nur ein Zufall sein oder wie oder was?, das muss kann soll 
darf geht doch gar nicht... **durchdreh**


[1] http://en.wikipedia.org/wiki/Guard_byte

von R. F. (rfr)


Lesenswert?

Ceterum Censeo redmondium esse delendam.
Gruss
Robert

von genervter Programmierer (Gast)


Lesenswert?

Wie bitte?

von R. F. (rfr)


Lesenswert?

Im alten Rom entstand ein Streit über den Umgang mit Karthago. Ein 
Senator, Cato d.Ä, hat zur Zerstörung Karthagos aufgerufen, in dem er 
jeder seiner Reden den Satz ' Ceterum Censeo Karthago esse delendam' 
angefügt hat (Ü: Im Übrigem bin ich der Meinung, daß Karthago zwerstört 
werden sollte.)

Nach einigen Jahren ist er dem Senat so sehr auf die Nerven gegangen, 
dass die Römer Karthago tatsächlich zerstörten.

Redmondium ist deer latinierte Name für Redmond, HQ of µSoft.

Gruss
Robert

von Huch (Gast)


Lesenswert?

Du bist zweifellos erregt und erschöpft. Das ist verständlich.

So ist auch erklärlich, das Du das pragma packed für ein "dämliches" 
hälst.
Das ist es aber nicht. Es hat, wie andere Spracheigenschaften auch 
seinen Sinn. So hat sich (hoffentlich) der Autor auch etwas dabei 
gedacht, wenn er es einsetzt.

Das es ohne packed läuft ist allein, keine hinreichende Erklärung. Das 
pragma hat ja wiegesagt einen Sinn und es muss erstmal geklärt werden 
auf welche Weise genau seine An- oder Abwesenheit die Funktion des 
Programmes beeinflusst.

Ich würde Dir ernsthaft empfehlen eine längere Pause zu machen. Eine 
wesentliche Information hast Du jetzt ermittelt. Jetzt mal ein bischen 
Abstand. Die Verurteilung des bösen pragmas wird Dir nicht wirklich 
weiterhelfen.

Viel Erfolg.

von Peter (Gast)


Lesenswert?

setze mal das alignment auf 1byte, das sollte den gleichen Effeckt wie 
das ((_packed_)) haben.

von genervter Programmierer (Gast)


Lesenswert?

Huch schrieb:
> So ist auch erklärlich, das Du das pragma packed für ein "dämliches"
> hälst.
Naja, ich weiss schon was das bewirkt (verhindert dass der Compiler 
Nullbytes zwischen die einzelnden Elemente "stopft") und dass das 
durchaus nützlich sein kann.

> So hat sich (hoffentlich) der Autor auch etwas dabei
> gedacht, wenn er es einsetzt.
Vermutlich um die genaue Anordnung der Bytes in der erzeugten Datei zu 
kennen / zu beeinflussen.

> Das es ohne packed läuft ist allein, keine hinreichende Erklärung.
Dem stimme ich durchaus zu.

> Das
> pragma hat ja wiegesagt einen Sinn und es muss erstmal geklärt werden
> auf welche Weise genau seine An- oder Abwesenheit die Funktion des
> Programmes beeinflusst.
Dürfte mit den erzeugten Dateien zu tun haben, s.o.

> Ich würde Dir ernsthaft empfehlen eine längere Pause zu machen.
Werd ich wohl machen, morgen ist Weihnachten...

> Die Verurteilung des bösen pragmas wird Dir nicht wirklich
> weiterhelfen.
Ich verurteile nichts und niemanden, aber es ist wohl verständlich dass 
man sich bei solchen Sachen irgendwann aufregt oder?

> Viel Erfolg.
Danke.

Peter schrieb:
> setze mal das alignment auf 1byte, das sollte den gleichen Effeckt wie
> das ((_packed_)) haben.
Da muss ich erstmal in die Doku gucken.

von genervter Programmierer (Gast)


Lesenswert?

R. Freitag schrieb:
> Im alten Rom entstand ein Streit über den Umgang mit Karthago.
> ...
> Redmondium ist deer latinierte Name für Redmond, HQ of µSoft.
Du hast Ideen... ;-)

von genervter Programmierer (Gast)


Lesenswert?

Sieg! Sieg! Es funktioniert! Sogar mit attribute packed! :-) :-) :-)

So, Problem gefunden und beseitigt. Wer findet den Fehler?

Header
1
typedef struct __attribute__ ((__packed__))
2
{
3
  ...
4
  InfoFeld_t * Felder;
5
  ...
6
} Entry_t;
7
8
typedef struct __attribute__ ((__packed__))
9
{
10
  ...
11
} InfoFeld_t;

Code
1
Entry_t * Data;
2
InfoFeld_t * Feldertmp;
3
uint32_t i,j,NbFelder;
4
5
//viel Code
6
//Platz für DB reservieren usw...
7
//viel Code
8
Feldertmp=realloc(Data[i].Felder,NbFelder*sizeof(InfoFeld_t));
9
//viel Code
10
Data[i].Felder[NbFelder].Index=j;

Mit der IDE von MS komme ich überhaupt nicht klar, bevor man da das 
Programm zum Compilieren gebracht hat hat man schon die Schnauze voll...
Der GDB hat auch nicht wirklich geholfen, über Code::Blocks ist das Ding 
eine bessere printf-Funktion und über die Kommandozeile... die Doku ist 
sehr sehr lang...
Schlussendlich hab ich den Ansatz von oben weiter verfolgt: Diverse 
Funktionsaufrufe (malloc usw.) per Präprozessor auf eigene Funktionen 
umgebogen welche den Aufruf zur eigentlichen Funktion weiterleiten, 
dabei jeweils etwas mehr Speicher reservieren, Guardbytes schreiben, 
Guardbytes prüfen, Debuginfo anlegen, ...
Nachdem das zwar einen Fehler bei einem memcpy() meldete aber ich im 
Code an dieser Stelle kein Problem fand einfach alle paar Zeilen 
memorycheck() (Eigenbau) aufgerufen und Bingo, eine Fehlermeldung mit 
Zeilennummer, ein scharfer Blick, ein zweiter Blick und der Fehler war 
gefunden.

Was für ein Aufwand für einen dämlichen Index!!!

von Daniel (Gast)


Lesenswert?

genervter Programmierer schrieb:
> Data[i].Felder[NbFelder].Index=j;

post fence error

im Übrigen, so eine Aufgabe schreit doch eher nach einer Skriptsprache

import random
random.choice(["Python","Ruby","Perl"])

von Klaus W. (mfgkw)


Lesenswert?

Rufus Τ. Firefly schrieb:
> Um das Studio selbst auch nicht, sondern primär um den integrierten
> Debugger. Mit dem Windbeutel* will man aus gutem Grund nicht arbeiten,
> der ist ... fast bäh.
>
> *) Windbg

Was hast du gegen Windbg?
Abgesehen davon, daß gelegentlich das alte sdb-Feeling aufkommt, ist
er doch gar nicht verkehrt.

Zumindest für Leute wie mich, die das VisualStudio sonst nur wegen
des Debuggers nehmen würden, ist es eine Alternative.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Klaus Wachtler schrieb:
> Zumindest für Leute wie mich, die das VisualStudio sonst nur wegen
> des Debuggers nehmen würden, ist es eine Alternative.

Äh, nein. Genau das ist er nicht, der VisualStudio-Debugger ist gefühlte 
15 Jahre jünger.

von Klaus W. (mfgkw)


Lesenswert?

Jünger ja, aber das Studio ist eine IDE mit allem Schnickschnack.
Um nur ein Programm zu debuggen, nervt es irgendwie, wenn man gar
kein Projekt in seinem Sinne hat.

Windbg kümmert sich darum nicht.
Nicht daß er besser oder moderner wäre, er ist einfach schlank
dagegen und funktioniert auch.

Wobei ich zugegebenermaßen zur Zeit recht selten debugge unter
Windows (mangels Fehlern natürlich :-)

von DirkB (Gast)


Lesenswert?

Klaus Wachtler schrieb:
> Wobei ich zugegebenermaßen zur Zeit recht selten debugge unter
> Windows (mangels Fehlern natürlich :-)

Dann programmierst du nicht unter Windows :)

von genervter Programmierer (Gast)


Lesenswert?

So, das Programm scheint zu funktionieren, weitere Fehler habe ich nicht 
gefunden.

Danke für die Unterstützung, besonders an Karl heinz Buchegger für das 
Stichwort "Guard-Byte" (simpel aber wirksam)!

Daniel schrieb:
> genervter Programmierer schrieb:
>> Data[i].Felder[NbFelder].Index=j;
>
> post fence error
schlichte Unaufmerksamkeit, wahrscheinlich hat genau in dieser Zeile das 
Telefon geklingelt. ;-)


> im Übrigen, so eine Aufgabe schreit doch eher nach einer Skriptsprache
>
> import random
> random.choice(["Python","Ruby","Perl"])
Mag sein, aber dazu muss man diese Sprachen auch erstmal beherrschen...

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.