*Markus: (C / Linux) Richtig debuggen?

Beitrag lesen

Hallo,

Hintergrund: Mein Programm stürzt in manchen Fällen ab und in manchen nicht, v.a. stürzt es fast immer ab, wenn ich mein Home-Verzeichnis einlese. Ich konnte den Fehler eingrenzen um zu wissen, wo er passiert, aber ich kann mir bisher nicht erklären warum gerade hier. Hier mal die Funktion in der es passiert:


File* readDirectory(char* dirname)  {
	
	 DIR *dir;
    struct dirent *dp;          // wird von readdir() zurückgeliefert
    size_t filecount = 0;       // number of entries in directory
    size_t i = 0;
    File* files;
    size_t file_len, dir_len;  //Wird für die Konkatenation des Filenames und des Dirs benötigt
    struct stat s;				//enthält alle Infos zu einem File

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

    while ((dp = readdir(dir)) != NULL)
        filecount++;

    files = (File *)calloc(filecount, sizeof(File *));  //Genauso viel Speicher reservieren wie man File-Zeiger hat
    if (!files) 												      //Für jede Datei wird hierbei ein neues File angelegt
        return NULL;

    rewinddir(dir);
    while (((dp = readdir(dir)) != NULL))   {
        file_len = strlen(dp->d_name);						//Verzeichnispfad konkatenieren
        dir_len = strlen(dirname);
        char newpath[file_len+dir_len+2]; 				//+2 weil \0 und / zw. dir- und filename
        strcpy(newpath, dirname);
        strcat(newpath, "/");
        strcat(newpath, dp->d_name);
        //Konkattenieren Ende
        stat(newpath, &s);										//get file status
        //Neues File alloziieren
        if ( (files[i] = (File)malloc(sizeof(File)) ) == NULL)   {
        	   while (i > 0) 									
                free(files[--i]);

            free(files);
            fprintf(stderr, "Insufficient memory for file allocation!");

            return NULL;
        }
        files[i]->inode_number = s.st_ino;
        printf("inode %ld\n", files[i]->inode_number);
        files[i]->filename = (char *)strdup(dp->d_name);
        printf("filename %s\n", files[i]->filename);	
    	  files[i]->lastedit = (char *)strdup(ctime(&s.st_mtime));
    	  printf("lastedit %s\n", files[i]->lastedit);
    	  files[i]->filesize = s.st_size;
    	  printf("filesize %ld\n", files[i]->filesize);
    	  files[i]->filetype = (char *)strdup(getFileType(dp->d_type));	 			//den Filetype übergeben und einen entsprechenden String zurückliefern
    	  printf("filetype %s\n", files[i]->filetype);
    	  files[i]->owner = s.st_uid;
    	  printf("owner %d\n", files[i]->owner);
    	  files[i]->group = s.st_gid;
    	  printf("group %d\n", files[i]->group);
    	 // (*files[i])->rating =
//    	  files[i]->path = (char *)strdup(newpath);
//    	  printf("path %s\n", files[i]->path);
    	 // (*files[i])->icon =
    	 // (*files[i]->metadata =

        i++;
    }
    printf("dir closed\n");
    closedir(dir);

    return files;
}

Wie man sieht, ließ ich mir sämtliche Inhalte ausgeben um den Fehler weiter eingrenzen zu können. Ein Crash passiert ab dieser Zeile files[i]->group = s.st_gid; Davor konnte ich bisher keine Crashs reproduzieren. Offensichtlich gibt es irgendwann Schwierigkeiten, die Gruppe einzulesen, oder was auch immer. Auf != NULL kann ich nicht überprüfen, da gcc mit einer Warnung meckert, ich würde zwischen einem Pointer und unsigned int vergleichen. Mit einem "if (s.st_gid)" kann ich die Crashs ebenso nicht abfangen.  Die Struktur dazu sieht im Übrigen so aus:


struct file   {
	unsigned long inode_number;
	char* filename;
	char* lastedit;
	unsigned long filesize;
	char* filetype;
	unsigned int owner;
	unsigned int group;
	unsigned int rating;
	char* path;
	char* icon;
	char** metadata;		//Array von Metadaten
};

Ironischerweise stürzt das Programm bei owner nicht ab, aber bei group. Den Unterschied verstehe ich bisher zwar nicht aber gut. Zu diesem Zweck wollte mir angewöhnen mit gdb zu arbeiten. Dummerweise bekomme ich keine vernünftige Ausgabe, da mir irgendwelche debugging symbols fehlen. Ich weiß, das man da irgendwelche Files benötigt aber wie weiß welche das sind und wo bekomme ich die her? Die Ausgabe sieht so aus:

markus@archy ~/C-Programme/Projekte/Dateibrowser $ gdb BrowserGUI GNU gdb 6.8 Copyright (C) 2008 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later http://gnu.org/licenses/gpl.html This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law.  Type "show copying" and "show warranty" for details. This GDB was configured as "i686-pc-linux-gnu"... (no debugging symbols found) (gdb) run Starting program: /home/markus/C-Programme/Projekte/Dateibrowser/BrowserGUI (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) [Thread debugging using libthread_db enabled] Error while reading shared library symbols: Cannot find new threads: generic error Cannot find new threads: generic error (gdb) bt #0  0xb80d29b1 in _dl_debug_state () from /lib/ld-linux.so.2 #1  0xb80d611c in dl_open_worker () from /lib/ld-linux.so.2 #2  0xb80d1ce6 in _dl_catch_error () from /lib/ld-linux.so.2 #3  0xb80d5a70 in _dl_open () from /lib/ld-linux.so.2 #4  0xb7659beb in dlopen_doit () from /lib/libdl.so.2 #5  0xb80d1ce6 in _dl_catch_error () from /lib/ld-linux.so.2 #6  0xb765a07c in _dlerror_run () from /lib/libdl.so.2 #7  0xb7659b21 in dlopen@@GLIBC_2.1 () from /lib/libdl.so.2 #8  0xb7a006c4 in g_module_open () from /usr/lib/libgmodule-2.0.so.0 #9  0xb7e4718c in load_modules () from /usr/lib/libgtk-x11-2.0.so.0 #10 0xb7e473e5 in _gtk_modules_settings_changed () from /usr/lib/libgtk-x11-2.0.so.0 #11 0xb7e474e1 in display_opened_cb () from /usr/lib/libgtk-x11-2.0.so.0 #12 0xb7a19aa8 in g_cclosure_marshal_VOID__OBJECT () from /usr/lib/libgobject-2.0.so.0 #13 0xb7a0cd42 in g_closure_invoke () from /usr/lib/libgobject-2.0.so.0 #14 0xb7a20fe8 in signal_emit_unlocked_R () from /usr/lib/libgobject-2.0.so.0 #15 0xb7a2235d in g_signal_emit_valist () from /usr/lib/libgobject-2.0.so.0 #16 0xb7a22657 in g_signal_emit_by_name () from /usr/lib/libgobject-2.0.so.0 #17 0xb7cb0671 in gdk_display_open () from /usr/lib/libgdk-x11-2.0.so.0 #18 0xb7c89ba5 in gdk_display_open_default_libgtk_only () from /usr/lib/libgdk-x11-2.0.so.0 #19 0xb7e2ccf1 in gtk_init_check () from /usr/lib/libgtk-x11-2.0.so.0 #20 0xb7e2cd24 in gtk_init () from /usr/lib/libgtk-x11-2.0.so.0 #21 0x08049925 in initMainWindow () #22 0x080496a0 in main () (gdb) quit

Selbst mit strace komme ich nicht weiter. Das sind die letzten Zeilen von strace:

open("/home/markus", O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY|O_CLOEXEC) = 4 getdents(4, /* 209 entries /, 32768)   = 4736 getdents(4, / 45 entries /, 32768)    = 1260 getdents(4, / 0 entries /, 32768)     = 0 lseek(4, 0, SEEK_SET)                   = 0 getdents(4, / 209 entries */, 32768)   = 4736 stat64("/home/markus/.", {st_mode=S_IFDIR|0755, st_size=8192, ...}) = 0 fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7094000 write(1, "inode 2321985\n"..., 14inode 2321985 )      = 14 write(1, "filename .\n"..., 11filename . )         = 11 open("/etc/localtime", O_RDONLY)        = 5 fstat64(5, {st_mode=S_IFREG|0644, st_size=2211, ...}) = 0 fstat64(5, {st_mode=S_IFREG|0644, st_size=2211, ...}) = 0 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7093000 read(5, "TZif2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\6\0\0\0\6\0\0\0\0\0"..., 4096) = 2211 _llseek(5, -28, [2183], SEEK_CUR)       = 0 read(5, "\nCET-1CEST,M3.5.0,M10.5.0/3\n"..., 4096) = 28 close(5)                                = 0 munmap(0xb7093000, 4096)                = 0 write(1, "lastedit Sun Oct 11 08:33:47 2009"..., 34lastedit Sun Oct 11 08:33:47 2009 ) = 34 write(1, "\n"..., 1 )                    = 1 write(1, "filesize 8192\n"..., 14filesize 8192 )      = 14 write(1, "filetype File\n"..., 14filetype File )      = 14 write(1, "owner 1000\n"..., 11owner 1000 )         = 11 write(1, "group 101\n"..., 10group 101 )          = 10 stat64("/home/markus/..", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 write(1, "inode 2\n"..., 8inode 2 )             = 8 write(1, "filename ..\n"..., 12filename .. )        = 12 stat64("/etc/localtime", {st_mode=S_IFREG|0644, st_size=2211, ...}) = 0 write(1, "lastedit Thu Jan 15 15:45:35 2009"..., 34lastedit Thu Jan 15 15:45:35 2009 ) = 34 write(1, "\n"..., 1 )                    = 1 write(1, "filesize 4096\n"..., 14filesize 4096 )      = 14 write(1, "filetype File\n"..., 14filetype File )      = 14 write(1, "owner 0\n"..., 8owner 0 )             = 8 write(1, "group 0\n"..., 8group 0 )             = 8 stat64("/home/markus/.java", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 write(1, "inode 3237876\n"..., 14inode 3237876 )      = 14 write(1, "filename .java\n"..., 15filename .java )     = 15 stat64("/etc/localtime", {st_mode=S_IFREG|0644, st_size=2211, ...}) = 0 write(1, "lastedit Thu Nov 27 22:39:32 2008"..., 34lastedit Thu Nov 27 22:39:32 2008 ) = 34 write(1, "\n"..., 1 )                    = 1 write(1, "filesize 4096\n"..., 14filesize 4096 )      = 14 write(1, "filetype File\n"..., 14filetype File )      = 14 write(1, "owner 1000\n"..., 11owner 1000 )         = 11 write(1, "group 101\n"..., 10group 101 )          = 10 stat64("/home/markus/C-Programme", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 write(1, "inode 2322006\n"..., 14inode 2322006 )      = 14 write(1, "filename C-Programme\n"..., 21filename C-Programme ) = 21 stat64("/etc/localtime", {st_mode=S_IFREG|0644, st_size=2211, ...}) = 0 --- SIGSEGV (Segmentation fault) @ 0 (0) --- +++ killed by SIGSEGV +++

Meine Frage lautet: Wie debugge ich richtig?

Danke. Viele Grüße, Markus