Forum: PC-Programmierung SQLITE sqlite3_str_reset() Seqmentfault


von Marco H. (damarco)


Lesenswert?

Hallo,

ich habe ein seltsames Problem das die Funktion sqlite3_str_reset() 
einen segmentfault auslöst.

Wirklich verstehe ich das nicht, denn die Funktion sqlite3_str_reset() 
setzt den bytecounter auf null und terminiert den string. Der 
Angeforderte Speicher bleibt erhalten. Passt dieser nicht rein wird 
durch sqlite3_str_append() neuer angefordert.

Ich habe solch eine ähnliche Funktion Programmiert zum erzeugen von json 
und diese funktioniert ohne Probleme. Auch mit dem SQL Code ;)

Was ich mir vorstellen könnte das der Pointer für den String intern 
verwendet wird bzw. etwas darauf zugreift.


sqlite Version 3.22.0-1ubuntu0.1

Jemand das Problem bekannt ?
Oder ich mach etwas falsch ?


Ich werde mal mit valgrid schauen, ewt. ist man dann schlauer...


Der Code sieht beispielhaft so aus...
1
sqlite3_str *sql= sqlite3_str_new(db); 
2
3
4
if(sql){
5
6
while(BEDINGUNG){
7
8
sqlite3_str_appendf(sql,"SQL COMMAND");
9
10
/* prepare or exec SQL Command */
11
.....
12
13
14
sqlite3_str_reset(sql) /* segemntfault */
15
16
}
17
18
sqlite3_free(sqlite3_str_finish(sql));
19
20
}

von Clemens L. (c_l)


Lesenswert?

Marco H. schrieb:
> Der Angeforderte Speicher bleibt erhalten.

Nein.
1
/*
2
** Reset an StrAccum string.  Reclaim all malloced memory.
3
*/
4
SQLITE_API void sqlite3_str_reset(StrAccum *p){
5
  if( isMalloced(p) ){
6
    sqlite3DbFree(p->db, p->zText);
7
    p->printfFlags &= ~SQLITE_PRINTF_MALLOCED;
8
  }
9
  p->nAlloc = 0;
10
  p->nChar = 0;
11
  p->zText = 0;
12
}

Du kannst genausogut in jedem Schleifendurchlauf eine neues Objekt 
erzeugen.

Der Grund des Problems ist wahrscheinlich anderer Code, der den Speicher 
überschreibt.

von Marco H. (damarco)


Lesenswert?

Mit dem Code wird das klar.

 "The sqlite3_str_reset(X) method resets the string under construction 
inside sqlite3_str object X back to zero bytes in length."

Hier er weniger...

was macht dann sqlite3_str_finish() genau ? Es gibt ja ein Memory Objekt 
zurück welches mit  sqlite3_free() freigegeben wird.


Wenn sqlite3_str_reset(X) nicht das macht was ich dachte kann ich auch 
sqlite3_mprintf() verwenden.

Aber Danke die Antwort war schon aufschlussreich genug ich werfe mal 
einen blick in den Code.

von Marco H. (damarco)


Lesenswert?

Ok ich habe es verstanden...

mit sqlite3_str_finish() wird das Object zerstört und der String 
zurückgegeben. Mit  sqlite3_free() wird der speicher vom String 
freigegeben der aus dem Object heraus gelöst wurde.

sqlite3_str_value() liefert nur einen pointer zum aktuellen String im 
Object.

sqlite3_str_reset(X) zerstört das object mit dem string. 
sqlite3_str_finish() und  sqlite3_free() ist unnötig da kein string aus 
dem Object heraus gelöst wurde und es bereits zerstört wurde.

von Clemens L. (c_l)


Lesenswert?

Es gibt zwei Speicherblöcke: das sqlite3_str-Objekt, und den Puffer für 
den eigentlichen String (zText).

sqlite3_str_reset() gibt nur zText frei; das Objekt ist dann in dem 
selben Zustand, den es direkt nach sqlite3_str_new() hatte.

sqlite3_str ist nur dann sinnvoll, wenn du einen String in mehreren 
Schritten zusammensetzen willst. Für dein Programm ist sqlite3_mprintf() 
in der Tat besser.

von Marco H. (damarco)


Lesenswert?

Ok verstanden ;) Vielen Dank !

Clemens L. schrieb:

> sqlite3_str_reset() gibt nur zText frei; das Objekt ist dann in dem
> selben Zustand, den es direkt nach sqlite3_str_new() hatte.

Ja aber warum kommt in dieser stelle es dann zum Seqmentfault ?
Denn genau das machte ja der Code, sqlite3_str_appendf() erzeugt einen 
neuen zText.

Ich kann ja mal schauen wo genau das Segmentfault auftritt.

: Bearbeitet durch User
von Clemens L. (c_l)


Lesenswert?

Marco H. schrieb:
> Ja aber warum kommt in dieser stelle es dann zum Seqmentfault ?

Weil anderer Code (den du nicht gezeigt hast) den Speicher zerhauen hat.

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.