Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (WinAPI, Konsole) » Was passiert, wenn... (Pointer)

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 <
000
25.05.2004, 11:14 Uhr
Unwissende
...die wirklich Unwissende 8-)


Hallöchen,

ich hab da mal eine Frage:
Und zwar hatte ich bis vor wenigen Minuten ständig den Fehler "Access Violation" (unter MFC).
Nun glaube ich, den Fehler gefunden zu haben:
Ich hatte einen Pointer of char:

C++:
// Module global variables
static char   *c_textpegel_2='0';


dieser wurde wie folgt ausgerufen:

C++:
if((diagnose ==0))
{
   sprintf(c_textpegel_2, " ok.\n");
}
else
{
   sprintf(c_textpegel_2, " failed (rc=0x%x). Diagnose see protocol file.\n", diagnose);
    }*/


Leider ist das ja ein längerer Text, also ein Array of Char (String), nun meine Frage:
Was passiert, wenn sprintf aufgerufen wird?
Der Compiler meckert nich...aber es kommt eben der schon o.g. Laufzeitfehler "Access Violation".
Ich vermute mal, dass sich Pointer of char mit String nicht so wirklich verträgt, oder?
Kann das sein, dass versucht wird, in Speicherbereiche zu schreiben, die gar nicht reserviert sind???
--
__________________________________
Unwissenheit ist vorläufig- Dummheit für immer
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
25.05.2004, 11:22 Uhr
(un)wissender
Niveauwart


sprintf kopiert "ok." nach c_textpegel_2.
Da hier aber kein Speicherplatz allokiert wurde, gibt es einen Laufzeitfehler.
Entweder du allokierst den benötigten Speicher dynamisch(new, malloc) oder aber statisch(static char buffer[128]), so geht es nicht.
Wenn du einem Pointer den Wert 0 zuweisen willst, dann mit 0 und nicht mit '0', das ist nämlich 48.
Diese Speicherstelle gehört sicherlich dem OS, da haste nichts zu suchen.


Bearbeitung:

Ein ausführliche Beschreibung zu sprintf findest du unter anderem hier .


--
Wer früher stirbt ist länger tot.

Dieser Post wurde am 25.05.2004 um 11:26 Uhr von (un)wissender editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
25.05.2004, 11:23 Uhr
virtual
Sexiest Bit alive
(Operator)


Hi,
also erstmal müsste Dir der Compiler schon mal mindestens eine (ernstzunehmende) Warnung bei

C++:
static char   *c_textpegel_2='0';


liefern, weil '0' ein einzelnes Zeichen ist, kein String. Wenn der Compiler nicht warnt, dann wird er c_textpegel_2 auf die Speicheradresse 0x00000030 oder so zeigen lassen, jedenfalls irgendwas falsches. Aber selbst wenn Du das nun verbesserst in

C++:
static char   *c_textpegel_2="0"; // Beachte: Doppelte Hochkommata


So ist c_textpegel_2 nun zwar ein gültiger Zeiger, aber eben einer, der
1. Readonly ist. Das sieht man ihm zwar nicht am Typen direkt an, aber er zeigt auf die feste Zeigerkette "0", was im Zweifel in einem Read-Only SPeichersegment liegt
2. Nur zwei Byte lang ist (Zeichen '0' und abschließendes 0 byte).

Das sprintf schreibt den Resultatstring nach c_textpegel_2, in jedem Fall also zuviel und im Zweifel an die falsche Stelle.
Ich würde Dir empfehlen:

C++:
static char  c_textpegel_2[256];


Oder den Umstieg auf C++ empfehlen (also string und stringstream verwenden)
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
25.05.2004, 11:42 Uhr
Unwissende
...die wirklich Unwissende 8-)


Hi,

okay, ich gebe zu, ich wollte mit:

C++:
// Module global variables
static char   *c_textpegel_2='0';


Das Char initialisieren...*schäm*

Den restlichen Quelltext habe ich von jemandem übernommen (Informatiker...) und ärgere mich jetzt schon wochenlang über irgendwelche Bugs, die nichtmal ich produziert habe und hinzu kommen meine eigenen Bugs

Dieser "textpegel" kommt an insgesamt 166Stellen im Prog vor... Wenn man mal davon ausgeht, dass die überzählen Chars "irgendwohin" in den Speicher geschrieben werden, wundert mich so langsam nichts mehr, wieso das Prog nie wirklich gelaufen ist...
--
__________________________________
Unwissenheit ist vorläufig- Dummheit für immer
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
25.05.2004, 11:44 Uhr
Unwissende
...die wirklich Unwissende 8-)


Ach, da fällt mir doch gerade noch ne Frage ein:
Wenn ich das jetzt wirklich so mache, wie es virtual gesagt hat:


C++:
static char  c_textpegel_2[256];


Und ich mit sprintf Text ins Array reinkopiere, was passiert dann, wenn mein Text mehr als 256Zeichen hat? Wird der überschüssige Text einfach abgeschnitten, oder hab ich hier wieder das gleiche PRoblem wie oben?
--
__________________________________
Unwissenheit ist vorläufig- Dummheit für immer
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
25.05.2004, 12:41 Uhr
virtual
Sexiest Bit alive
(Operator)


Nein, der Text wird einfach in den Speicher geschrieben, so lang wie der Text ist. Eigentlich hast Du fünf möglichkeiten das Problem zu lösen:

1. Der mit am wenigsten Aufwand verbundene Ansatz dürfte sein, einen sehr großen Speicherbereich zu reservieren, also wenn Du denkst daß der Text auch mal 300 Zeichen lang ist, den Buffer entsprechend vergrößern. Das Problem liegt auf der Hand: Dein Programm läuft dennoch in den Wald, wenn Du falsch gedacht hast und trotzdem mehr in den Buffer eingeschriben wird, irgendwo.

2. Du Stellst sicher, daß niemals mehr als 256 (oder was auch immer) Zeichen reingeschrieben werden. Eigentlich sind hier vor allem die Strings, die per %s eingefügt werden die Hauptursache für Bufferoverflows. Da könnte man sich etwa so behelfen:

C++:
sprintf(c_textpegel_2, "Fehlermeldung: %s", text);


würde ja problematisch werden, wenn text recht lang wäre, so daß nachher zuviel nach c_textpegel_2 geschrieben würde. Das kann man umgehen, indem man sagt:

C++:
sprintf(c_textpegel_2, "Fehlermeldung: %*.*s", 100, 100, text);


Das sagt: egal, oib nun text länger als 100 Zeichen ist oder nicht, kopiere max. 100 Zeichen in den resultatstring.

3. Du verwendest snprintf, da kannst du angeben, wie lang c_textpegel_2 wirklich ist, also was wirklich reinpasst. snprintf gibt es seit dem C99 Standard, wird aber auch von den meisten älteren Compilern unterstützt.

4. Machst es etwa so:

C++:
static std::string c_textpegel_2;
...
if((diagnose ==0))
{
   c_textpegel_2 = "ok.\n";
}
else
{
   std::stringstream sstr;
   sstr<<"failed (rc="<<diagnose<<"). Diagnose see protocol file.\n";
    c_textpegel_2 = sstr.str();
}


Das wäre die C++ lösung, die ich empfehlenswert finde.

5. Wenn Du MFC verwenden darfst/kannst, kannst Du ja mal die Klasse CString anschauen, die hat glaube ich eine format Methode, die dem sprintf sehr ähnlich ist. Aber das weiß ich letztlich nicht genau, ich kenne mich mit dem Schweinkram nicht so gut aus.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
25.05.2004, 12:44 Uhr
~Spacelord
Gast



Zitat:
virtual postete
Hi,
also erstmal müsste Dir der Compiler schon mal mindestens eine (ernstzunehmende) Warnung bei

C++:
static char   *c_textpegel_2='0';


liefern, weil '0' ein einzelnes Zeichen ist, kein String. Wenn der Compiler nicht warnt....


Vielleicht täusch ich mich ja aber '0' wird in diesem Fall doch als Textkonstante
interpretiert und bereits während der Compilierung als feste Adresse umgesetzt,somit dürfte die Zuweisung schon ok sein.
Ist in diesem Zusammenhang natürlich trotzdem Tinnef.

MfG Spacelord
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
25.05.2004, 12:48 Uhr
virtual
Sexiest Bit alive
(Operator)


Ja, mit der festen Adresse erwähnte ich das ja etwa vier worte hinter dem Ende des von dir geposteten Zitats aus meinem Post. Nur dachte ich, daß ein vernünftiger compiler hier warnen sollte, weil man fest adressen rein stilistisch eh schon mal nur gecastet angeben sollte. Von einem Compiler würde ich erwarten:

C++:
char* ptr1 = '0'; // Warnung
char* ptr2 = (char*)'0'; // Keine warnung


--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
008
25.05.2004, 13:53 Uhr
Unwissende
...die wirklich Unwissende 8-)


.......ich entscheide mich für Möglichkeit 2.) (Begrenzung der Länge des Strings auf 256 Zeichen) Scheint im Moment die einfachste und leichteste Möglichkeit zu sein...


--
__________________________________
Unwissenheit ist vorläufig- Dummheit für immer
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
009
25.05.2004, 16:52 Uhr
0xdeadbeef
Gott
(Operator)


CString der MFC hat auf jeden Fall eine Methode CString::Format(char *fmt, ...), sie sich wie [sf]+printf verhält. Du könntest das damit zum Beispiel so machen:

C++:
CString s;
s.Format(" failed (rc=0x%x). Diagnose see protocol file.\n", diagnose);
c_textpegel_2 = s.GetBuffer(0); //ich glaube, dass das so war - mache in letzer Zeit zum Glück :wink: wenig MFC.


--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 <     [ C / C++ (WinAPI, Konsole) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: