Seite 1 von 1

Unauffindbare Speicherverletzung

Verfasst: Sa Sep 14, 2013 3:51 pm
von darksider3
Moin!
Ich habe seit mehrern Wochen das Problem, dass ich eine Speicherverletzung bei Eingabedaten(argv[1+n]) bekomme. Dabei gibt es eine Art und Weise, wie es ohne Funktioniert und eine, die den Speicher überrennt.

Das Programm soll eigentlich eine Eingabe bekommen, die Wörter daraus zählen, allesamt in ein eigenes Array verfrachten und die Wörter einzeln ausgeben.

Das Programm ist folgendes:

Code: Alles auswählen

 //Own Error-Constants
#define TS_ERROR 3
#define TS_OK 0

#include <iostream>
#include <cstdio>
//using namespace std;
/**
    mystrlen does count all letters in *str
    @param const char *str  String to count
    @return     x                Number of counted letters.
 */
int mystrlen(const char *str)
{
  int x=0;
  for(; str[x] != '\0';x++)
  {
    //Do nothing.
  }
  return x;
}

char *ToString(const char* arg1, const char* arg2)
{
  int *arglen  = new (int[2]);
  int x=0;
  arglen[0] = mystrlen(arg1);
  arglen[1] = mystrlen(arg2);
  char *internstr=new ( char [ ( arglen [0] + arglen [1] + 1 ) ] );
  for(int i=0; i < arglen[0];i++)
  {
    internstr[x] =arg1[i];
    x++;
    //@DEBUG=printf(internstr);
  }
  for(int i=0; i < arglen[1]; i++)
  {
    internstr[x] = arg2[i];
    //@DEBUG=printf(internstr);
    x++;
  }
  internstr[x]='\0';
  return internstr;
}

int countWords(const char* toCount)
{
  int leng = mystrlen(toCount);
  int words=0;

  int imwort=0;
  for(int i=0;i < leng;i++)
  {
    if(toCount[i] != ' ' && imwort == 0)
    {
      imwort =1;
      words++;
    }
    if(toCount[i] == ' ')
    {
      imwort =0;
    }
  }
  return words;
}

int countLetters(const char* toCount)
{
  int xstabe=0;
  for(; toCount[xstabe] != ' ' && toCount[xstabe] != '\0'; xstabe++)
  {
    //Do nothing;; Only counting
  }
  return xstabe;
}

char *copyFirstWord(char const *str)
{
  int size=countLetters(str);
  char *sfinal=new(char[size+1]);
  int i=0;
  for(; i < size;i++)
  {
    sfinal[i]=str[i];
    //cout << str[i];
  }
  sfinal[i+1] = '\0';
  return sfinal;
}


int main(int argc, char **argv)
{

  if(argc == 1)
  {
    std::cout << "Nothing given; Exit" << std::endl;
    return 1;
  }

  int words=countWords(argv[1]);
  /*@DEBUG=int intwords=countLetters(argv[1], words[1][2]);
  */
  char **fullWords=new char*[ (words) ];
  /*
  cout << copyFirstWord()*/
 // int *size=0;
  int x=0;
  int uberspringe=0;
  for(int i=0; argv[1][i] != '\0';i++)
  {
    if(argv[1][i] != ' ')
    {
      fullWords[x]=copyFirstWord(&argv[1][i]);
      uberspringe=countLetters(&argv[1][i]);
      i=i+uberspringe;
      uberspringe=0;
      //std::cout << fullWords[x] << std::endl;
      x++;
    }
    else
    {
      i++;
    }
  }

    //std::cout << fullWords;
  delete[](fullWords);
  return TS_OK;
}
Die Funktionierende Eingabe ist eine, welche am Ende ein Leerzeichen beinhaltet.
Beispielsweise:

Code: Alles auswählen

./Program "Hallo Welt! "
So wird alles korrekt erledigt.

Sobald ich aber das Leerzeichen weglasse, wird der Speicher - wie schon erwähnt - offensichtlich überrannt:
(Ausgabe)

Code: Alles auswählen

*** Error in `./Program': free(): invalid next size (fast): 0x09fff008 ***
======= Backtrace: =========
/lib/i386-linux-gnu/i686/cmov/libc.so.6(+0x75e72)[0xb750fe72]
/lib/i386-linux-gnu/i686/cmov/libc.so.6(+0x76bb0)[0xb7510bb0]
/usr/lib/i386-linux-gnu/libstdc++.so.6(_ZdlPv+0x1f)[0xb76f84bf]
/usr/lib/i386-linux-gnu/libstdc++.so.6(_ZdaPv+0x1b)[0xb76f850b]
./ToString2[0x8048ab4]
/lib/i386-linux-gnu/i686/cmov/libc.so.6(__libc_start_main+0xf5)[0xb74b38f5]
./ToString2[0x8048681]
======= Memory map: ========
08048000-08049000 r-xp 00000000 08:01 524544     /home/user/Desktop/Programmiersprachen/C++/Aufgaben/ToString2
08049000-0804a000 rw-p 00000000 08:01 524544     /home/user/Desktop/Programmiersprachen/C++/Aufgaben/ToString2
09fff000-0a020000 rw-p 00000000 00:00 0          [heap]
b7498000-b749a000 rw-p 00000000 00:00 0 
b749a000-b7643000 r-xp 00000000 08:01 654309     /lib/i386-linux-gnu/i686/cmov/libc-2.17.so
b7643000-b7644000 ---p 001a9000 08:01 654309     /lib/i386-linux-gnu/i686/cmov/libc-2.17.so
b7644000-b7646000 r--p 001a9000 08:01 654309     /lib/i386-linux-gnu/i686/cmov/libc-2.17.so
b7646000-b7647000 rw-p 001ab000 08:01 654309     /lib/i386-linux-gnu/i686/cmov/libc-2.17.so
b7647000-b764a000 rw-p 00000000 00:00 0 
b764a000-b7666000 r-xp 00000000 08:01 654346     /lib/i386-linux-gnu/libgcc_s.so.1
b7666000-b7667000 rw-p 0001b000 08:01 654346     /lib/i386-linux-gnu/libgcc_s.so.1
b7667000-b7668000 rw-p 00000000 00:00 0 
b7668000-b76a9000 r-xp 00000000 08:01 654326     /lib/i386-linux-gnu/i686/cmov/libm-2.17.so
b76a9000-b76aa000 r--p 00040000 08:01 654326     /lib/i386-linux-gnu/i686/cmov/libm-2.17.so
b76aa000-b76ab000 rw-p 00041000 08:01 654326     /lib/i386-linux-gnu/i686/cmov/libm-2.17.so
b76ab000-b778b000 r-xp 00000000 08:01 266736     /usr/lib/i386-linux-gnu/libstdc++.so.6.0.17
b778b000-b778f000 r--p 000e0000 08:01 266736     /usr/lib/i386-linux-gnu/libstdc++.so.6.0.17
b778f000-b7790000 rw-p 000e4000 08:01 266736     /usr/lib/i386-linux-gnu/libstdc++.so.6.0.17
b7790000-b7797000 rw-p 00000000 00:00 0 
b77af000-b77b2000 rw-p 00000000 00:00 0 
b77b2000-b77b3000 r-xp 00000000 00:00 0          [vdso]
b77b3000-b77d2000 r-xp 00000000 08:01 661772     /lib/i386-linux-gnu/ld-2.17.so
b77d2000-b77d3000 r--p 0001f000 08:01 661772     /lib/i386-linux-gnu/ld-2.17.so
b77d3000-b77d4000 rw-p 00020000 08:01 661772     /lib/i386-linux-gnu/ld-2.17.so
bfe9f000-bfec0000 rw-p 00000000 00:00 0          [stack]
Abgebrochen
Leider kann ich den Fehler, den ich wie schon erwähnt mehrere Wochen schon habe, nicht finden.

Habt ihr evtl. eine Ahnung, wieso dies passiert, und wie ich das gelöst kriege?

Danke euch!

MFG

Re: Unauffindbare Speicherverletzung

Verfasst: Sa Sep 14, 2013 5:50 pm
von Xin
Ich gebe Dir mal einen Tipp:

Da ist die Zeile:

Code: Alles auswählen

  char **fullWords=new char*[ (words) ];
Du forderst also die Anzahl von words an Zeiger an.

Und da ist die Zeile

Code: Alles auswählen

      fullWords[x]=copyFirstWord(&argv[1][i]);
x darf also nur Werte zwischen 0 bis "words" annehmen. Ansonsten überschreibst eventuell etwas im Speicher, was zu willkürlichem Verhalten führt.

Prüfe mal, ob das passt.

Re: Unauffindbare Speicherverletzung

Verfasst: Sa Sep 14, 2013 6:24 pm
von darksider3
Danke dir.
Soweit funktioniert es jetzt - in den letzten Zeilen musste nur eine if-Abfrage rein:

Code: Alles auswählen

      if(x < words)
      {
        fullWords[x]=copyFirstWord(&argv[1][i]);
        uberspringe=countLetters(&argv[1][i]);
        i=i+uberspringe;
        uberspringe=0;
        //std::cout << fullWords[x] << std::endl;
        std::cout << x  << std::endl;
        x++;
      }
.. Wörter sind gezählt, gespeichert und x bleibt innerhalb des zugelassenen Wertbereichs.. :)