Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » Sigsegv

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
29.07.2003, 10:05 Uhr
xodiak



Hallo Leute!

ich habe hier zwei Funktionen, process_dir und read_dir.
Das was ich mit den Funktionen machen will funktioniert zuverlässig, solange ich Zugriff auf das Verzeichnis habe. Habe ich auf ein Verzeichnis keine Zugriffsrechte, so bricht er mir mit einem SIGSEGV in der markierten Zeile ab (while(*dir)). der GDB sagt mir vor dem Absturz, dass dir auf 0x0 zeigt -> Logisch, Schutzverletzung. Der Denkfehler muss also irgendwo in read_dir begraben sein. Kann mir jemand auf die Sprünge helfen?
Danke schonmal,

Gruß
xodi


C++:
float process_dir(char *directory, char *tname, int *filestotal, float *sizetotal, unsigned int level)
{
  struct dirnames **dir, **sav;
  char *path = malloc(1024);
  float dsize = 0;
  int dfiles = *filestotal;
  sav = dir = read_dir(directory, &dsize, filestotal, tname);
  if(debug) printf("process_dir %d\n", debug++);

  while(*dir)          // <-------------------- Hier kommt der SIGSEGV
  {
      if((strlen(directory)+strlen((*dir)->name))  > 1022) path = realloc(path, strlen(directory)+strlen((*dir)->name) + 2);
      if(strlen(directory) == 1)
        snprintf(path,strlen((*dir)->name)+3,"/%s",(*dir)->name);
      else
         snprintf(path,strlen(directory)+strlen((*dir)->name)+2,"%s/%s",directory,(*dir)->name);
      dsize += process_dir(path,tname, filestotal, sizetotal, (level + 1));
      free((*dir)->name);
      free(*(dir++));
  }
  insert_level(((float)dsize)/1048576, directory, ((*filestotal)-dfiles));
  if(level == 1) check_legal(tname, directory, (float)(dsize)/1048576, ((*filestotal)-dfiles), strlen(getvalue(tname, "transdir")));
  free(path);
  if(debug) printf("process_dir Ende\n");
  return dsize;
}

struct dirnames **read_dir(char *dir, float *thisdirsize, int *thisdirfiles, char *tname)
{
  static char *path;
  struct dirnames **dl;
  struct dirent *ent;
  struct stat lst;
  DIR *d;
  int ne, p = 0,
      bigsize = 1048576 * atoi(getvalue(tname, "bigsize")),
      olddate = time((time_t *)NULL) - atoi(getvalue(tname, "olddate"))*3600*24;

  if(debug) printf("read_dir %d\n", debug++);

  if ((d=opendir(dir)) == NULL) return NULL;

  dl = (struct dirnames **) malloc(sizeof(struct dirnames *) * (ne = 400));
  path = malloc(1024);

  while((ent = (struct dirent *)readdir(d)))
  {
    if (!(strcmp("..",ent->d_name) && strcmp(".",ent->d_name) && strncmp(".snapshot",ent->d_name, 9))) continue;

    if((strlen(dir)+strlen(ent->d_name)) > 1022)
        path = realloc(path, (strlen(dir)+strlen(ent->d_name)+2));
    snprintf(path,strlen(dir)+strlen(ent->d_name)+2,"%s/%s",dir,ent->d_name);


    if (lstat(path,&lst) < 0 || ((lst.st_mode & S_IFMT) == S_IFLNK))
    {
        (*thisdirfiles)++;
        continue;
    }
    if((lst.st_mode & S_IFMT) == S_IFDIR)
    {
        dl[p] = (struct dirnames*) malloc(sizeof(struct dirnames));
        if(ent->d_name == NULL)
            dl[p++]->name = scopy(ent->d_name);
        else
            dl[p++]->name = scopy("Error opening directory");
        if(p>ne) dl = (struct dirnames **) realloc(dl,sizeof(struct dirnames *) * (ne += 100));
        continue;
    }
    (*thisdirsize) += lst.st_size;
    (*thisdirfiles)++;
    

  }
  closedir(d);
  free(path);
  dl[p] = NULL;
    if(debug) printf("read_dir Ende\n");
  return dl;
}


--
There's always one more bug.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
29.07.2003, 10:16 Uhr
0xdeadbeef
Gott
(Operator)


Schau mal hier:

C++:
  if ((d=opendir(dir)) == NULL) return NULL;


Ziemlich am Anfang. Wenn du keine Zugriffsrechte hast, wirst du wohl das Verzeichnis nicht öffnen können, und er gibt dir NULL zurück - und das versuchst du zu dereferenzeiren, was natürlich nicht hinhaut. Workaround:

C++:
if(dir)


vor die while-Schleife schreiben.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
29.07.2003, 10:32 Uhr
ao

(Operator)


Ich vermute, du bist an folgender Stelle aus read_dir rausgeflogen:


C++:
if ((d=opendir(dir)) == NULL) return NULL;


Dann passiert beim Eintritt in while (*dir) genau das von dir Beschriebene. Aber da du gdb schon kennst, dürfte der Nachweis für dich einfach sein.

Der Fehler ist, daß process_dir ungeprüft einen gültigen dir-Pointer erwartet, read_dir aber auch NULL liefern kann. Du könntest stattdessen while(dir && *dir) prüfen.

Übrigens hast du auch vergessen, dir am Ende von process_dir wieder freizugeben -> Speicherleck. Natürlich nur, wenn es nicht NULL ist!

ao
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
29.07.2003, 10:43 Uhr
xodiak



argh, wie dämlich und unausgeschlafen kann man eigentlich sein!?

Danke! Ihr habt natürlich recht:


C++:
if ((d=opendir(dir)) == NULL) return NULL;



ist das Problem und


C++:
while(dir && *dir);



die "Lösung".

@ao : Aber trotzdem *darf* ich dir nicht am Ende von process_dir freigeben.
Das letzte Element wird ja schon in der Schleife freigegeben.

Danke Leute!
--
There's always one more bug.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
29.07.2003, 10:50 Uhr
ao

(Operator)



Zitat:
xodiak postete
@ao : Aber trotzdem *darf* ich dir nicht am Ende von process_dir freigeben.
Das letzte Element wird ja schon in der Schleife freigegeben.


Hast recht.
ao
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
29.07.2003, 11:18 Uhr
0xdeadbeef
Gott
(Operator)


@xodiak: Ich hab mir erlaubt, den Post, in dem du um die Löschung gebeten hast, gleich mitzulöschen. Er ergab irgendwie keinen Sinn mehr, wenn der andere Post weg war...

Was den Code angeht: Effizienter wäre

C++:
if(dir) while(*dir) {
    //...
}


Es gibt ja keine Chance, dass dir im Verlauf der Schleife auf NULL gesetzt wird.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra

Dieser Post wurde am 29.07.2003 um 11:19 Uhr von 0xdeadbeef editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
29.07.2003, 11:23 Uhr
xodiak



hast nochmal recht -> gefixt.
Dann muss er natürlich nur eine condition im Schleifenkopf prüfen -> macht Sinn.
--
There's always one more bug.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 <     [ C / C++ (ANSI-Standard) ]  


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: