Chris: C Speicherproblem ...

Hallo zusammen,

ich habe ein komisches Problem mit einem kleinen C Programm das mir bald meinen Verstand nimmt ;-(

Ich Deklariere eine Variable "query" um diese in meiner Funtkion zu benutzen.

Aber beim ersten Durchlauf meiner Whileschleife hat die Variable den Inhalt "4{@4{@".

Beim 2ten durchlauf ist die Variable dann so wie sie eigentlich sein soll, ich kann das absolut nicht verstehen ;-(

Hier mal das Stück Code (gekürzt, aber der gleiche Effekt):

void RunJobs()
{
   MYSQL_ROW  row, zon;
   MYSQL_RES  *res,*res1;
   FILE *stream;
   FILE *zone;
   char *str,*query;
   int size=0, i;

mysql_query(mysql, "SELECT * FROM domains WHERE MID=0");
   CheckError();

res = mysql_store_result(mysql);
   CheckError();

mysql_field_seek (res, 0);

while ((row = mysql_fetch_row (res)) != NULL)
   {
       query =(char *) malloc(11);
       printf("Hier der Inhalt von Query: %s\n",query);
       free(query);
   }

mysql_free_result(res);

}

Der Code lässt einsehen das ich dort einen Query für eine Mysql Abfrage zusammen bauen möchte, habe das ganze aber wegen der Übersicht auf das Minimum begrenzt.

Habt Ihr vieleicht Rat für mich ?

Wenn ich hier mit meiner Frage im falschen Forum gelandet bin gebt mir doch bitte einen Tipp wo ich noch schauen könnte ...

Jedenfalls danke und viele Grüße,

Chris

  1. Moin,

    query =(char *) malloc(11);

    Du allozierst dynamisch Speicher. Über diesen Speicher kann man dann aber keine Aussagen machen (im Allgemeinen), er ist mit undefinierten Werten gefüllt. Wenn du willst dass da was bestimmtes drinsteht, dann musst du es reinschreiben. Oder du benutzt gleich calloc(), welches den Speicher freundlicherweise gleich ausnullt.

    --
    Henryk Plötz
    Grüße aus Berlin
    ~~~~~~~~ Un-CDs, nein danke! http://www.heise.de/ct/cd-register/ ~~~~~~~~
    ~~ Help Microsoft fight software piracy: Give Linux to a friend today! ~~
    1. Hi,

      danke für deine Antwort, so schaut das Ganze eigentlich aus:

      while ((row = mysql_fetch_row (res)) != NULL)
         {
             str = "SELECT * FROM zonen WHERE DID=";

      size=0;
             size+=strlen(str);
             size+=strlen(row[0]);

      query =(char *) malloc(size + 11);

      strcat(query, str);
             strcat(query, row[0]);

      printf("Hier der Query: %s\n",query);

      free(query);
         }

      sollte doch eigentlich ok sein, oder ?

      Ich ermittle den benötigten Speicherplatz in der Variable size, reserviere dann den Platz für query mit malloc, dann kopiere ich den Inhalt von str und row[0] in die Variable Query ;-)

      Bei der ersten Ausgabe des Query schaut des so aus:

      Hier der Query: 4{@4{@SELECT * FROM zonen WHERE DID=1

      Nach der ersten läuft alles Prima:

      Hier der Query: SELECT * FROM zonen WHERE DID=2

      Hab ich da was absolut nicht verstanden ? ;-(

      Viele Grüße ...

      Chris

      1. Moin,

        query =(char *) malloc(size + 11);

        Wie gesagt, der Inhalt des Speichers auf den query zeigt ist undefiniert (lies: auf gängigen Systemen zufällig). Bei dir steht halt zufällig 4{@4{@ gefolgt von einem Nullbyte drin.

        strcat(query, str);

        Damit hängst du an den aktuellen Inhalt des Strings etwas an. Das macht nichts weiter als das erste Nullbyte im String zu suchen und dahin den anderen String zu kopieren.

        Hab ich da was absolut nicht verstanden ? ;-(

        Offensichtlich.

        --
        Henryk Plötz
        Grüße aus Berlin
        ~~~~~~~~ Un-CDs, nein danke! http://www.heise.de/ct/cd-register/ ~~~~~~~~
        ~~ Help Microsoft fight software piracy: Give Linux to a friend today! ~~
        1. Hi,

          Wie gesagt, der Inhalt des Speichers auf den query zeigt ist undefiniert

          Ok, Anlauf 2 ;-)

          char str[50]="SELECT * FROM zonen WHERE DID=",query[61]="";

          Damit lege ich dann jetzt fest das dort nichts unsinniges reinrutscht.

          while ((row = mysql_fetch_row (res)) != NULL)
             {
                 strcat(query, str);
                 strcat(query, row[0]);

          printf("Hier der Query: %s\n",query);
             }

          Nun ist im Speicher das was drin sein soll, aber er hängt logischer Weise an Query immer wieder str und row[0] an, was ich aber vermeiden möchte ;-)

          Daher meine Frage, wie kann ich die Variable query am Ende der Whileschleife wieder leeren ?

          query=""; klappt nett, free is klar geht auch nett, aber was bleibt mir da noch ?

          Viele Grüße und danke,

          Chris

          1. Hi,

            Wie gesagt, der Inhalt des Speichers auf den query zeigt ist undefiniert

            Ok, Anlauf 2 ;-)

            char str[50]="SELECT * FROM zonen WHERE DID=",query[61]="";

            Du hast alle " escaped?
            Gut, geh' ich einfach mal von aus ;-)

            Nun ist im Speicher das was drin sein soll, aber er hängt logischer Weise an Query immer wieder str und row[0] an, was ich aber vermeiden möchte ;-)

            Daher meine Frage, wie kann ich die Variable query am Ende der Whileschleife wieder leeren ?

            Einfach NULen oder ein '\0' an den Anfang setzen:
            memset(str,0,strlen(str));
            oder
            str[0] = '\0';

            query=""; klappt nett.

            Klappt deshalb nicht, weil du so keinen String kopieren kannst und auch ein C-String der Länge 0 ist ein String.

            so short

            Christoph Zurnieden

            PS:
            Sag' mal: was machst Du da eigentlich? Ist ja lobenswert, das Du C lernst, aber meisnt Du nicht, das Du erstmal die Grundlagen lernen solltest bevor Du an sowas rangehst?
            CZ

            1. Hallo,

              char str[50]="SELECT * FROM zonen WHERE DID=",query[61]="";

              Du hast alle " escaped?
              Gut, geh' ich einfach mal von aus ;-)

              Na ja, ich vermute die Anweisung nach dem Kommaoperator soll so etwas wie

              query[61] = '\0';

              bewirken.

              Nun ist im Speicher das was drin sein soll, aber er hängt logischer Weise an Query immer wieder str und row[0] an, was ich aber vermeiden möchte ;-)

              Wie wäre es, wenn sich der Ausgangsposter mit den diversen String-Funktionen beschäftigt, ein Ausgangspunkt neben dem Handbuch ist z.B. http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_5.html

              strcpy bzw. strncpy statt strcat wäre schon mal eine Massnahme. Ich verstehe allerdings nicht, warum der OP seinen Puffer um 11 Zeichen größer macht als den Inhalt, ein Zeichen sollte für '\0' genügen.

              Ich weiss, es handelt sich um _alte_ Informationen. Aber soviel hat sich da nicht getan :-)

              Freundliche Grüsse,

              Vinzenz

              1. Hi,

                Nun ist im Speicher das was drin sein soll, aber er hängt logischer Weise an Query immer wieder str und row[0] an, was ich aber vermeiden möchte ;-)

                Wie wäre es, wenn sich der Ausgangsposter mit den diversen String-Funktionen beschäftigt, ein Ausgangspunkt neben dem Handbuch ist z.B. http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_5.html

                strcpy bzw. strncpy statt strcat wäre schon mal eine Massnahme.

                Na, so einfach ist das alles nicht.

                Ich verstehe allerdings nicht, warum der OP seinen Puffer um 11 Zeichen größer macht als den Inhalt, ein Zeichen sollte für '\0' genügen.

                Na, doch, das ist schon verständlich, wenn man den ganzen Thread verfolgt hat ;-)

                Ich weiss, es handelt sich um _alte_ Informationen. Aber soviel hat sich da nicht getan :-)

                Die neueste ist hier:
                http://www.gnu.org/software/libc/manual/
                Ist aber auch schon recht alt.

                so short

                Christoph Zurnieden

            2. Hi,

              Du hast alle " escaped?
              Gut, geh' ich einfach mal von aus ;-)

              Öhm, nein ;-)

              Aber in dem String kommen keine ' oder " vor, oder meinst du was anderes ?

              str[0] = '\0';

              Klappt bestens, danke ;-)

              PS:
              Sag' mal: was machst Du da eigentlich? Ist ja lobenswert, das Du C lernst, aber meisnt Du nicht, das Du erstmal die Grundlagen lernen solltest bevor Du an sowas rangehst?
              CZ

              Das ganze ist/wird eine Verwaltung (html,php,mysql) für Zonefiles.

              Ist wahrlich mein erster Versuch etwas in C zu schreiben ...

              Das mit den Grundlagen ist so eine Sache, wenn ich mir das alles nur trocken durchlese bleibt kaum was hängen, daher lerne ich quasie mit der Aufagabe ;-)

              Hast du vieleicht eine Info wo ich ein Forum finden kann das sich intensiver mit dem Thema C beschäftigt wo ich auch im Arhciv ein bisel lesen kann ?

              Meist sind ja die Anfängerfragen immer die gleichen ;-)

              Viele Grüße & danke,

              Chris

              1. Hi,

                Du hast alle " escaped?
                Gut, geh' ich einfach mal von aus ;-)

                Öhm, nein ;-)

                Aber in dem String kommen keine ' oder " vor, oder meinst du was anderes ?

                Ja, ich meine 'was anderes.
                Aber der Witz scheint ja nicht gut rauszukomen, wenn gleich zwei Leute das nicht komisch finden, was? ;-)

                Jaja, sagt man's mal durch die Blume ... ;-)

                str[0] = '\0';

                Klappt bestens, danke ;-)

                Ja, das funktioneirt. Ist aber kein wirklich guter Stil, da so die Reste im Speicher verbleiben. Ist in 99,99% der Fälle egal, aber wenn Du mal z.B. Paßwörter auf diese Weise löscht ...

                Nein, nimm besser memset()

                PS:
                Sag' mal: was machst Du da eigentlich? Ist ja lobenswert, das Du C lernst, aber meisnt Du nicht, das Du erstmal die Grundlagen lernen solltest bevor Du an sowas rangehst?
                CZ

                Das ganze ist/wird eine Verwaltung (html,php,mysql) für Zonefiles.

                Und warum dann C?
                Nein, ernsthafte Frage: warum brauchst Du etwas in C?

                Ist wahrlich mein erster Versuch etwas in C zu schreiben ...

                Ja, das ist bemerkenswert auffällig ;-)

                Soll Dich aber natürlich nicht davon abhalten!

                Das mit den Grundlagen ist so eine Sache, wenn ich mir das alles nur trocken durchlese bleibt kaum was hängen, daher lerne ich quasie mit der Aufagabe ;-)

                Ja, das kann ich gut nachvollziehen ;-)

                Hast du vieleicht eine Info wo ich ein Forum finden kann das sich intensiver mit dem Thema C beschäftigt wo ich auch im Arhciv ein bisel lesen kann ?

                Keine Ahnung, bin ich ehrlich. Sowas hier?
                news:alt.comp.lang.learn.c-c++
                Google Cache dieser Newsgroup:
                http://groups.google.de/groups?hl=de&lr=&ie=ISO-8859-1&q=alt.comp.lang.learn.c-c%2B%2B&btnG=Suche

                Meist sind ja die Anfängerfragen immer die gleichen ;-)

                C-FAQ
                http://www.eskimo.com/~scs/C-faq/top.html
                Eine kurze Buchliste:
                http://www.comeaucomputing.com/booklist/

                Tutorials:
                Das Berühmte:
                http://www.lysator.liu.se/c/bwk-tutor.html
                Der "Klassiker"
                http://www.cs.cf.ac.uk/Dave/C/CE.html
                Hat so einen netten Namen ;-)
                http://www.strath.ac.uk/IT/Docs/Ccourse/

                Eien lose Sammlung vom Maintainer der C-FAQ
                http://www.eskimo.com/~scs/cclass/cclass.html

                Etwas in deutsch:
                http://www.schellong.de/c.htm
                http://www.lemps.ch/doku/

                Ansonsten kannst Du mich ja auch noch löchern ;-)

                so short

                Christoph Zurnieden

  2. hi!

    while ((row = mysql_fetch_row (res)) != NULL)
       {
           query =(char *) malloc(11);
           printf("Hier der Inhalt von Query: %s\n",query);
           free(query);
       }

    Dass du query hier gar keinen Wert zuweist, sondern einfach einen zufälligen Bereich
    im Speicher (inkl. dessen Inhalt), hat Henryk dir ja schon geschrieben. Aber außerdem
    möchtest du sehr wahrscheinlich den Rückgabewert von malloc() nicht casten!

    bye, Frank!

    --
    Never argue with an idiot. He will lower you to his level and then
    beat you with experience.
    1. Hi,

      Aber außerdem
      möchtest du sehr wahrscheinlich den Rückgabewert von malloc() nicht casten!

      Warum nicht? Es ist nicht verboten und C++ braucht es. Woher wilst Du wissen, das deer gesamte Code nicht in C++ genutzt werden soll?
      http://www.google.com/groups?selm=9sFIb.9066%24nK2.4505%40nwrddc01.gnilink.net&output=gplain

      Gut, war ja auch nur 'ne rethorische Frage ;-)

      so short

      Christoph Zurnieden

      1. hi!

        Aber außerdem
        möchtest du sehr wahrscheinlich den Rückgabewert von malloc() nicht casten!
        Warum nicht? Es ist nicht verboten und C++ braucht es. Woher wilst Du wissen, dass
        der gesamte Code nicht in C++ genutzt werden soll?

        In C++ würde man weder malloc() noch C-Casts verwenden.

        bye, Frank!

        --
        Never argue with an idiot. He will lower you to his level and then
        beat you with experience.
  3. Hallo Chris,

    Aber beim ersten Durchlauf meiner Whileschleife hat die Variable den Inhalt "4{@4{@".

    Das ist Zufall.

    Beim 2ten durchlauf ist die Variable dann so wie sie eigentlich sein soll, ich kann das absolut nicht verstehen ;-(

    Das ist ebenfalls Zufall.

    char *str,*query;

    Warum nicht

    char query[11];

    while ((row = mysql_fetch_row (res)) != NULL)
       {
           query =(char *) malloc(11);

    Du allozierst dynamisch Speicher. Es könnte fehlschlagen. Prüfst Du den Erfolg der Anforderung?

    printf("Hier der Inhalt von Query: %s\n",query);

    Es ist Zufall, was in dem Speicher steht. Bei der Verwendung von

    calloc

    würden Nullen drin stehen. Mir ist allerdings schleierhaft, warum Du dynamisch Speicher anforderst. Hier ist meiner Meinung nach ein statischer Puffer sinnvoller. Die Doku zu malloc und calloc findest Du bei einem Linux-System mit

    man malloc

    Freundliche Grüsse,

    Vinzenz