abclinuxu.cz AbcLinuxu.cz itbiz.cz ITBiz.cz HDmag.cz HDmag.cz abcprace.cz AbcPráce.cz
AbcLinuxu hledá autory!
Inzerujte na AbcPráce.cz od 950 Kč
Rozšířené hledání
×
    dnes 19:55 | Zajímavý projekt

    Průkopnická firma FingerWorks kolem roku 2000 vyvinula vícedotykové trackpady s gesty a klávesnice jako TouchStream LP. V roce 2005 ji koupil Apple, výrobu těchto produktů ukončil a dotykové technologie využil při vývoji iPhone. Multiplatformní projekt Apple Magic TouchstreamLP nyní implementuje funkcionalitu TouchStream LP na současném Apple Magic Trackpad, resp. jejich dvojici. Diskuze k vydání probíhá na Redditu.

    |🇵🇸 | Komentářů: 0
    dnes 18:22 | Nová verze

    Byla vydána nová verze 10.3 sady aplikací pro SSH komunikaci OpenSSH. Přináší řadu bezpečnostních oprav, vylepšení funkcí a oprav chyb.

    Ladislav Hagara | Komentářů: 0
    dnes 15:11 | Zajímavý software

    Cloudflare představil open source redakční systém EmDash. Jedná se o moderní náhradu WordPressu, která řeší bezpečnost pluginů. Administrátorské rozhraní lze vyzkoušet na EmDash Playground.

    Ladislav Hagara | Komentářů: 1
    dnes 14:00 | Komunita

    Bratislava OpenCamp 2026 zverejnil program a spustil registráciu. Štvrtý ročník komunitnej konferencie o otvorených technológiách prinesie 19 prednášok na rôzne technologické témy. Konferencia sa uskutoční v sobotu 25. apríla 2026 v priestoroch FIIT STU v Bratislave.

    Ladislav Hagara | Komentářů: 0
    dnes 13:44 | Humor

    Na iVysílání lze zhlédnout všechny díly kultovního sci-fi seriálu Červený trpaslík.

    Ladislav Hagara | Komentářů: 4
    dnes 04:44 | IT novinky

    Společnost Valve aktualizovala přehled o hardwarovém a softwarovém vybavení uživatelů služby Steam. Podíl uživatelů Linuxu dosáhl v březnu 5,33 % (Windows -4,28 %, OSX +1,19 %, Linux +3,10 %). Nejčastěji používané linuxové distribuce jsou Arch Linux, Linux Mint a Ubuntu. Při výběru jenom Linuxu vede SteamOS Holo s 24,48 %. Procesor AMD používá 67,48 % hráčů na Linuxu.

    Ladislav Hagara | Komentářů: 3
    včera 23:22 | IT novinky

    Společnost Apple slaví padesáté narozeniny. Založena byla 1. dubna 1976.

    Ladislav Hagara | Komentářů: 1
    včera 22:33 | Nová verze

    FreeTube, desktopový klient pro YouTube využívající lokální API, byl vydán ve verzi 0.24.0. Toto velké opravné vydání implementuje SABR (Server-Based Adaptive Bit Rate), což řeší část nedávných problémů s načítáním videí z YouTube, a aktualizuje základní komponenty jako Electron nebo přehrávač Shaka Player.

    |🇵🇸 | Komentářů: 2
    včera 16:33 | Humor

    Je tu opět apríl. O víkendu zmizel kamion s 12 tunami tyčinek KitKat. Firmy to využívají k aprílovým žertům. Groupon má super akci. Koupíte 1 tyčinku a dostanete 100 zdarma. Ryanair si přelepil letadla. Šéf Outlooku se ptá, proč mají v baráku 14 beden tyčinek KitKat (𝕏). Prusa Research představuje Prusa Pro ACU a vysvětluje proč přílišné sušení škodí vaším filamentům. Telefon Sony Xperia má miliónnásobný zoom (𝕏). PC.net představil Super Ultrabox 2600 se zajímavými parametry. Další aprílové novinky například na April Fools' Day On The Web.

    Ladislav Hagara | Komentářů: 2
    včera 13:22 | IT novinky

    Společnost OpenAI, která stojí za chatovacím robotem s umělou inteligencí (AI) ChatGPT, získala od investorů 122 miliard USD (2,6 bilionu Kč). Hodnota společnosti tak dosáhla 852 miliard dolarů (více než 18 bilionů Kč). Nejnovější kolo investování se stalo největší, jaké zatím firma uskutečnila, a peníze mají posílit ambiciózní plány rozšíření výpočetní kapacity, datových center a nábor talentů.

    Ladislav Hagara | Komentářů: 15
    Které desktopové prostředí na Linuxu používáte?
     (15%)
     (7%)
     (1%)
     (12%)
     (30%)
     (3%)
     (5%)
     (1%)
     (14%)
     (23%)
    Celkem 1205 hlasů
     Komentářů: 29, poslední 31.3. 11:17
    Rozcestník

    Dotaz: Segfault pri strcpy v rekurzivni fci

    tomes.io avatar 12.1.2014 20:11 tomes.io | skóre: 12 | blog: tomesh
    Segfault pri strcpy v rekurzivni fci
    Přečteno: 594×
    Ahoj, prosim o pomoc s debugem fce, ktera rekurzivne monitoruje dany adresar:
    void watch_dir(char *file) {
        int ret;
        struct stat buf;
        struct dirent *data;
    	char *path = NULL;
    
        if (lstat(file, &buf))
            return;
    
        if (!S_ISDIR(buf.st_mode))
            return;
    
        DIR *dir = opendir(file);
    
        if (dir == NULL)
            return;
    
    	//char *path2 = NULL;
    	
        while ((data = readdir(dir)) != NULL) {
            if (strcmp(data->d_name, ".") == 0 ||
                    strcmp(data->d_name, "..") == 0)
                continue;
    
            if (strstr(data->d_name, ".") == data->d_name)
                continue;
    
            path = (char *) malloc(strlen(file) + strlen(data->d_name) +1 * sizeof (path));
            asprintf(&path, "%s/%s", file, data->d_name);
    
    
            if (lstat(path, &buf))
                continue;
            //If it's a dir then launch watch_dir himself on it
            if (S_ISDIR(buf.st_mode))
                watch_dir(path);
    
            
        }
    
        closedir(dir);
        // now set watch for the argument of watch_dir
        ret = inotify_add_watch(inotify, file, IN_ALL_EVENTS);
    
        if (ret == -1) {
            printf("%s\n", file);
            perror("Error in watcher setting\n");
            exit(0);
        }
    
        strcpy(files[ret], file);
    	free(path);
    	path = NULL;
    
        return;
    }
    
    Valgrind hlasi:
    
    ==10177== Invalid write of size 1
    ==10177==    at 0x4A09350: strcpy (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==10177==    by 0x4011C9: watch_dir (testclient1.c:147)
    ==10177==    by 0x401138: watch_dir (testclient1.c:132)
    ==10177==    by 0x401138: watch_dir (testclient1.c:132)
    ==10177==    by 0x401138: watch_dir (testclient1.c:132)
    ==10177==    by 0x401138: watch_dir (testclient1.c:132)
    ==10177==    by 0x401274: handle_event (testclient1.c:169)
    ==10177==    by 0x401945: main (testclient1.c:353)
    ==10177==  Address 0x704180 is not stack'd, malloc'd or (recently) free'd
    ==10177== 
    ==10177== 
    ==10177== Process terminating with default action of signal 11 (SIGSEGV)
    ==10177==  Access not within mapped region at address 0x704180
    ==10177==    at 0x4A09350: strcpy (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==10177==    by 0x4011C9: watch_dir (testclient1.c:147)
    ==10177==    by 0x401138: watch_dir (testclient1.c:132)
    ==10177==    by 0x401138: watch_dir (testclient1.c:132)
    ==10177==    by 0x401138: watch_dir (testclient1.c:132)
    ==10177==    by 0x401138: watch_dir (testclient1.c:132)
    ==10177==    by 0x401274: handle_event (testclient1.c:169)
    ==10177==    by 0x401945: main (testclient1.c:353)
    
    
    
    
    Problem je tedy v nejake ctvrte rekurzi. Myslim, ze blbe mallocuju path, ktery se pridava do rekurzivniho volani. A pokud ho blbe nemallocuju, tak ho urcite blbe uvolnuji pomoci free. Chci vas poprosit o radu, jak to spravne osetrit.

    Fce je soucasti klienta, ktery rekurzivne pomoci inotify monitoruje zadany adresar. Cely klient je zde:
    
    int inotify;
    char files[1024][1024];
    struct inotify_event *event;
    struct sockaddr_in serv_addr;
    int sockfd;
    
    
    /**
     * @brief Test if only a correct message is about to be sent
     * 
     * @param s
     * @return 
     */
    
    int is_empty(const char *s) {
    
        char buff[1024];
        strcpy(buff,s);;
        
        buff[strlen(buff)] = '\0';
    
        if (buff[0] == '/' || isdigit(buff[0])){      
            return 1;
        }
       
        return 0;
    }
    
    /**
     * @brief Sends a message to the server.
     * 
     * @param message
     * @param portno
     */
    
    void send_msg(char *message, int portno) {
        
        int n;
        char recvbuff[256];
        
        serv_addr.sin_port = htons(portno);
        sockfd = socket(AF_INET, SOCK_STREAM, 0);
        bzero(recvbuff, 256);
    
        if (sockfd < 0)
            perror("send_msg: ERROR opening socket");
    
        if (connect(sockfd, (struct sockaddr *) &serv_addr,
                sizeof (serv_addr)) < 0)
            perror("send msg: ERROR connecting");
    
        n = write(sockfd, message, strlen(message) +1);
    
        if (n < 0)
            perror("send msg: ERROR writing to socket");
    
        n = read(sockfd, recvbuff, 256);
    
        if (n < 0)
            perror(" send_msg: ERROR reading from socket");
    
        printf("%s\n", recvbuff);
        free(message);
    	message = NULL;
        close(sockfd);
    }
    
    /**
     * @brief Recursively watches a directory.
     * 
     * @param file
     */
    
    void watch_dir(char *file) {
        int ret;
        struct stat buf;
        struct dirent *data;
    	char *path = NULL;
    
        if (lstat(file, &buf))
            return;
    
        if (!S_ISDIR(buf.st_mode))
            return;
    
        DIR *dir = opendir(file);
    
        if (dir == NULL)
            return;
    
    	//char *path2 = NULL;
    	
        while ((data = readdir(dir)) != NULL) {
            if (strcmp(data->d_name, ".") == 0 ||
                    strcmp(data->d_name, "..") == 0)
                continue;
    
            if (strstr(data->d_name, ".") == data->d_name)
                continue;
    
            path = (char *) malloc(strlen(file) + strlen(data->d_name) +1 * sizeof (path));
            asprintf(&path, "%s/%s", file, data->d_name);
    
    
            if (lstat(path, &buf))
                continue;
            //If it's a dir then launch watch_dir himself on it
            if (S_ISDIR(buf.st_mode))
                watch_dir(path);
    
            
        }
    
        closedir(dir);
        // now set watch for the argument of watch_dir
        ret = inotify_add_watch(inotify, file, IN_ALL_EVENTS);
    
        if (ret == -1) {
            printf("%s\n", file);
            perror("Error in watcher setting\n");
            exit(0);
        }
    
        strcpy(files[ret], file);
    	free(path);
    	path = NULL;
    
        return;
    }
    
    /**
     * @brief Handles notified events.
     * 
     * @param path
     * @param dest
     */
    
    void handle_event(char *path, char *dest, int portno) {
        
        char *message = (char *) malloc((strlen(path) * sizeof (message)) + 10);   
    
        if (event->mask & IN_CREATE) {
            if (event->mask & IN_ISDIR) {
                
                printf("The directory %s was created.\n", event->name);
                watch_dir(dest);
                
            } else {
                
                printf("The file %s was created.\n", event->name);
            }
    
            asprintf(&message, "%d:%d:%s", IN_CREATE,
                    (int) strlen(dest), path);
            
            int j = is_empty(message);
    
            if (j == 1)
                send_msg(message, portno);
            
            //printf("")
        }
    
        else if (event->mask & IN_DELETE) {
            if (event->mask & IN_ISDIR) {
                
                printf("The directory %s was deleted.\n", event->name);
                
            } else {
                
                printf("The file %s was deleted.\n", event->name);
            }
    
            asprintf(&message, "%d:%d:%s", IN_DELETE,
                    (int) strlen(dest), path);
    
            int j = is_empty(message);
    
            if (j == 1)
                send_msg(message, portno);
        }
        
        else if (event->mask & IN_MODIFY) {
            if (event->mask & IN_ISDIR) {
                
                printf("The directory %s was modified.\n", event->name);
                
            } else {
    
                printf("The file %s was modified.\n", event->name);
            }
    
            asprintf(&message, "%d:%d:%s", IN_MODIFY,
                    (int) strlen(dest), path);
    
            int j = is_empty(message);
    
            if (j == 1)
                send_msg(message, portno);
        }
    
        else if (event->mask & IN_MOVED_FROM) {
            if (event->mask & IN_ISDIR) {
    
                printf("Directory %s with cookie %d has been "
                        "moved from the sync directory.\n",
                        event->name, event->cookie);
                
            } else {
                
                printf("Directory %s with cookie %d has been "
                        "moved from the sync directory.\n",
                        event->name, event->cookie);
            }
    
            asprintf(&message, "%d:%d:%s", IN_MOVED_FROM,
                    (int) strlen(dest), path);
            
            int j = is_empty(message);
    
            if (j == 1)
                send_msg(message, portno);
        }
        else if (event->mask & IN_MOVED_TO) {
            if (event->mask & IN_ISDIR) {
                
                printf("Directory %s with cookie %d has been "
                        "moved to the sync directory.\n",
                        event->name, event->cookie);
    			watch_dir(dest);
                
            } else {
                
                printf("Directory %s with cookie %d has been "
                        "moved to the sync directory.\n",
                        event->name, event->cookie);
            }
    
            asprintf(&message, "%d:%d:%s", IN_MOVED_TO,
                    (int) strlen(dest), path);
            
            int j = is_empty(message);
    
            if (j == 1)
                send_msg(message, portno);
        }
        
        else {
    		
    		free(message);
    		message = NULL;
    	}
       
       free(path);
       path = NULL;
    }
    
    int main(int agrc, char *argv[]) {
    
        int portno, n;
        struct hostent *server;
        char buffer[4096];
        char *dest = malloc(strlen(argv[1]) + 1);
    
        strcpy(dest, argv[1]);
        inotify = inotify_init();
    
        if (!inotify) {
            perror("Open inotify device");
            fprintf(stderr, "Are you sure your kernel supports inotify?\n");
        }
        //launch recursive watching
        watch_dir(dest);
        printf("Start monitoring!\n");
        portno = atoi(argv[2]);
        server = gethostbyname("localhost");
    
        if (server == NULL) {
            fprintf(stderr, "ERROR, no such host\n");
            exit(0);
        }
    
        bzero((char *) &serv_addr, sizeof (serv_addr));
        serv_addr.sin_family = AF_INET;
        
        bcopy((char *) server->h_addr,
                (char *) &serv_addr.sin_addr.s_addr,
                server->h_length);
    
        /*First connection to the server. 
         * Client sends to a server a path 
         * to client's "dropbox" folder*/
        serv_addr.sin_port = htons(portno);
        sockfd = socket(AF_INET, SOCK_STREAM, 0);
    
        if (connect(sockfd, (struct sockaddr *) &serv_addr,
                sizeof (serv_addr)) < 0)
            perror("ERROR connecting");
    
        n = write(sockfd, dest, strlen(dest) + 1);
    
        if (n < 0)
            perror("ERROR writing to socket");
    
        close(sockfd);
    
        while (1) {
            int ret;
            int i = 0;
            ret = read(inotify, buffer, 4096);
    
            if (ret < 0)
                perror("read");
    
            if (ret == 0)
                sleep(1);
    
    		char *path = NULL; 
    		
            while (i < ret) {
                char *name = NULL;
                event = (struct inotify_event *) &buffer[i];
    
                if (event->len)
                    name = &buffer[i] + sizeof (struct inotify_event);
               
                path = (char *) malloc(1024 * sizeof (path));
    
                asprintf(&path, "%s/%s", files[event->wd], name);                     
                handle_event(path, dest, portno);           
                i += sizeof (struct inotify_event) +event->len;
    			//free(path);
    			//path = NULL;
    			
            }
        }
    
        close(sockfd);
        return 0;
    }
    
    
    

    Řešení dotazu:


    Odpovědi

    12.1.2014 20:54 Šangala | skóre: 56 | blog: Dutá Vrba - Wally
    Rozbalit Rozbalit vše Re: Segfault pri strcpy v rekurzivni fci
    Jestli to dobře chápu tak tady by mělo být (ale nectějí se mi počítat řádky...):
    path = (char *) malloc((strlen(file) + strlen(data->d_name) + 2) * sizeof (char));

    Pravidlo: „Když nevíš, závorkuj.“ :-)

    Vytvořil jsi tam tím velmi nahodilou věc… a musíš +2 bo jeden je ten '/' a druhý '\0' na konci.
    To, že trpíš stihomamem, ještě neznamená, že po tobě nejdou. ⰞⰏⰉⰓⰀⰜⰉ ⰗⰞⰅⰜⰘ ⰈⰅⰏⰉ ⰒⰑⰎⰉⰁⰕⰅ ⰏⰉ ⰒⰓⰄⰅⰎ ·:⁖⁘⁙†
    rADOn avatar 13.1.2014 10:33 rADOn | skóre: 44 | blog: bloK | Praha
    Rozbalit Rozbalit vše Re: Segfault pri strcpy v rekurzivni fci
    To je sice chyba ale akorat tim zblajzne vic pameti nez potrebuje. Jestli pocitam dobre zavorky tak se mallocuje pro kazdou polozku v adresari, ale free je mimo blok takze upusti akorat tu posledni.
    "2^24 comments ought to be enough for anyone" -- CmdrTaco
    13.1.2014 11:42 Šangala | skóre: 56 | blog: Dutá Vrba - Wally
    Rozbalit Rozbalit vše Re: Segfault pri strcpy v rekurzivni fci

    JSem se jen zběžně juknul a akdž bylo napsáno mallocuju, tak jsem se podíval jen na malloc.

    Více, pravda - o 3 nebo 7 byte, sizeof(char) je vždy 1, asi jsem moc nepřemýšlel, viděl jsem divné násobení velikostí a hotovo...

    Jo-jo free(path);, by mělo být ve smyčce také - na jejím konci, ne až mimo na konci fce, jinak dochází k „memory leak“.

    Nicméně problém bude spíše v zápis mimo files[1024][1024] na 147 řádku (hlášení je o zápisu mimo alokovaný prostor):

    strcpy(files[ret], file);
    nevím jakých hodnot nabývá watch descriptor, nicméně nikde se nepíše, že je < 1024, jak je asi zamýšleno v kódu, stejně jako maximální možná délka pro file, parametr fce watch_dir, 1023 znaků).

    K autorovi: „Ošetřit návrat malloc() na NULL je opravdu dobrý nápad a základ...“

    To, že trpíš stihomamem, ještě neznamená, že po tobě nejdou. ⰞⰏⰉⰓⰀⰜⰉ ⰗⰞⰅⰜⰘ ⰈⰅⰏⰉ ⰒⰑⰎⰉⰁⰕⰅ ⰏⰉ ⰒⰓⰄⰅⰎ ·:⁖⁘⁙†
    tomes.io avatar 13.1.2014 18:46 tomes.io | skóre: 12 | blog: tomesh
    Rozbalit Rozbalit vše Re: Segfault pri strcpy v rekurzivni fci
    Jo, navrat malloc urcite, na to jsem pozapomnel :( Ale mallocem to tedy asi nebude, protoze problem pretrvava i po oprave. Ono to asi opravdu vypada na problem s hodnotou watch descriptoru, protoze problem nastava pouze pri zkopirovani adresare se slozitou stromovou strukturou, napriklad zdrojaky kernelu. Kdyz zvysim pole na 10000:
    char files[10000][1024];
    Tak to nepada. Ale to mi prijde uz dost robustni.

    Premyslim, co s tim. Bud do protokolu (ktery k programu musim psat) napisu proste, ze to ma takove a takove omezeni, nebo se s tim nejak vyporadam dynamicky, jenze jak?
    13.1.2014 18:58 axel
    Rozbalit Rozbalit vše Re: Segfault pri strcpy v rekurzivni fci
    Jak? malloc?
    rADOn avatar 13.1.2014 19:26 rADOn | skóre: 44 | blog: bloK | Praha
    Rozbalit Rozbalit vše Re: Segfault pri strcpy v rekurzivni fci
    Takže abych to shrnul: ty kopíruješ jména do staticky alokovaného pole a divíš že je chyba když tomu dáš sežrat víc souborů než kolik se jich do toho pole vejde?

    "2^24 comments ought to be enough for anyone" -- CmdrTaco
    tomes.io avatar 13.1.2014 21:08 tomes.io | skóre: 12 | blog: tomesh
    Rozbalit Rozbalit vše Re: Segfault pri strcpy v rekurzivni fci
    Nedivim, nevsiml jsem si, ze to je zpusobene zrovna timto, nyni je to jasne.
    13.1.2014 21:16 Sten
    Rozbalit Rozbalit vše Re: Segfault pri strcpy v rekurzivni fci
    Pozor na to, tohle sežere skoro 10 MiB stacku, ale normální velikost stacku je 8 MiB.
    14.1.2014 02:23 Sten
    Rozbalit Rozbalit vše Re: Segfault pri strcpy v rekurzivni fci
    Jo aha, ono je to statické, ne na stacku
    13.1.2014 21:51 Šangala | skóre: 56 | blog: Dutá Vrba - Wally
    Rozbalit Rozbalit vše Re: Segfault pri strcpy v rekurzivni fci

    Nesouvisí ale neošetření alokace paměti je fatální chyba v 99 % případů.

    Watch descriptor jako index pole je CHYBA, dle man-u inotify_add_watch vrací při úspěchu nezápornou hodnotu, tedy >= 0 <= INT_MAX, nikde není zaručeno, že to začne na 0. Zvětšení velikosti pole není robustní, ale stále stejně špatně a postup (zvětšování pole až to vyjde) je nesprávný.

    Vypořádat se - rozhodně dynamicky a to plně, tedy i pro délku, céčko má výhodu (oproti c++), že lze použít fci realloc a ta často umí to, že alokovanou pamět „jen prodlužuje“ (pokud nelze tak alokuje novou a obsah zkopíruje), takže si můžeš nachystat třeba na 1000 položek a pak po 1000 přidávat - jen bych přehodnotil přístup watch descriptor = index.

    Malá rada, když jsi v situaci kdy nevíš co dělat (v dané fázi, či nedostatkem zkušeností co s tím) při zklamání čehokoliv (třeba malloc), prostě to zabij, vytvoř si macro či třeba fci, která vypíše řádek s jedním volitelným textovým parametrem (jako komentář) a v té fci volej exit(), případně abort(). A tuto fci použij při zklamání takového kódu, v budoucnu si můžeš, postupně jednoduchým grepem ta místa lokalizovat a postupně řešit.

    #define MY_KILL_ON_ERROR(text) { \
      fprintf(stderr,"KILLED ON ERROR: %s\nAt: %s Line: %d" \
        ,text,__FILE__, __LINE__); \
      exit(3); \
    }
    
    Použití:
     MY_KILL_ON_ERROR("Not enought memory")

    To, že trpíš stihomamem, ještě neznamená, že po tobě nejdou. ⰞⰏⰉⰓⰀⰜⰉ ⰗⰞⰅⰜⰘ ⰈⰅⰏⰉ ⰒⰑⰎⰉⰁⰕⰅ ⰏⰉ ⰒⰓⰄⰅⰎ ·:⁖⁘⁙†
    rADOn avatar 14.1.2014 10:29 rADOn | skóre: 44 | blog: bloK | Praha
    Rozbalit Rozbalit vše Re: Segfault pri strcpy v rekurzivni fci
    …céčko má výhodu (oproti c++), že lze použít fci realloc…
    Proč by to v C++ nemělo jít? Mě naopak při pohledu na ten kód jako první napadlo že jeden std::vector by autorovi ušetřil spoustu potíží.

    "2^24 comments ought to be enough for anyone" -- CmdrTaco
    14.1.2014 10:50 Šangala | skóre: 56 | blog: Dutá Vrba - Wally
    Rozbalit Rozbalit vše Re: Segfault pri strcpy v rekurzivni fci

    Asi jsem to blbě napsal. C++ by mu usnadnilo hodně věcí, hlavně ve správě paměti - o tom žádná. (Pokud ovšem použije dané kontejnery, ale bez nich by to zas tak úplně nebylo C++ ;))

    Poukazoval jsem na rozdíl, že v C lze použít fci realloc, která může daný blok paměti jen zvětšit, což je efektivnější než alokovat druhý blok a obsah paměti kopírovat.

    OT: A může ji i zmenšit bez alokace nového bloku oboje na rozdíl od uváděného std::vector což nemá v tomto případě žádný faktický dopad, ale rozdíl to je a někdy se to hodí.

    To, že trpíš stihomamem, ještě neznamená, že po tobě nejdou. ⰞⰏⰉⰓⰀⰜⰉ ⰗⰞⰅⰜⰘ ⰈⰅⰏⰉ ⰒⰑⰎⰉⰁⰕⰅ ⰏⰉ ⰒⰓⰄⰅⰎ ·:⁖⁘⁙†
    tomes.io avatar 14.1.2014 20:30 tomes.io | skóre: 12 | blog: tomesh
    Rozbalit Rozbalit vše Re: Segfault pri strcpy v rekurzivni fci
    Ano, C++ by mi opravdu usnadnilo spoustu veci, jenze tohle je predmet na ciste C a POSIX v Linuxu :)
    tomes.io avatar 14.1.2014 20:29 tomes.io | skóre: 12 | blog: tomesh
    Rozbalit Rozbalit vše Re: Segfault pri strcpy v rekurzivni fci
    Diky za makro a rady, pouziji tedy dynamickou alokaci.
    jen bych přehodnotil přístup watch descriptor = index.
    Me bohuzel zadny lepsi zpusob nenapada. Potreboval jsem rekurzivne monitorovat celou adresarovou stukturu, inotify rekurzivne nemonitoruje a tohle se mi jevilo jako jedine reseni. Napada te nejake lepsi?

    15.1.2014 01:21 Pavel Löbl | skóre: 7 | blog: vadnej_pixel
    Rozbalit Rozbalit vše Re: Segfault pri strcpy v rekurzivni fci
    No nejspis jde o to, ze nikde neni receno ze funkce inotify_add_watch bude postupne vracet cisla cisla 0 az N pri jednotlivych, po sobe jdoucich volanich. Takze pouziti pole (i kdyz dynamicky alokovaneho) pro mapovani deskriptoru na adresare neni nejspis spravna cesta. Naivni pristup je pouziti spojaku, v lepsim pripade me napada hashovaci tabulka nebo nejaky vyhledavaci strom. Pripadne drzet deskriptory v setridenem poli. Pak by byla slozitost pridani deskriptoru n*log(n) (setrideni) a vyhledavani log(n) (binarni puleni). Toto je sice celkem jednoduche na implementaci, ale hash tabulka bude zrejme v prumeru rychlejsi.
    tomes.io avatar 16.1.2014 09:38 tomes.io | skóre: 12 | blog: tomesh
    Rozbalit Rozbalit vše Re: Segfault pri strcpy v rekurzivni fci
    Zjistil jsem, ze mi klient spatne notifikuje modifikace souboru v prave prejmenovanem adresari. Vypis toho ,co prijde serveru:
    
    Received message: 256:32:/home/tomesh/Development/dropbox/New Folder/Text File
    Received message: 2:32:/home/tomesh/Development/dropbox/New Folder/Text File
    Received message: 64:32:/home/tomesh/Development/dropbox/New Folder
    Received message: 128:32:/home/tomesh/Development/dropbox/u
    Received message: 256:32:/home/tomesh/Development/dropbox/New Folder/.Text File.kate-swp
    Received message: 2:32:/home/tomesh/Development/dropbox/New Folder/.Text File.kate-swp
    
    
    256 je inotify flag pro CREATE. 2 pro MODIFY, 64 pro MOVED_FROM a 128 pro MOVED_TO. Vypis rika, ze se adresar New Folder prejmenoval na 'u'. Nejdriv se odstrani stary(64) a pak se vlozi novy (128) se stejnym cookie. Muj klient tohle zachycuje a server se podle toho zaridi.

    Klient tedy spatne monitoruje, tak mi pak server hodi segfault, protoze dostane zpravu o zmene souboru v neexistujicim adresari.

    Muze to byt zrovna timhle, ze pouzivam polep ro mapovani deskriptoru?
    16.1.2014 15:28 Pavel Löbl | skóre: 7 | blog: vadnej_pixel
    Rozbalit Rozbalit vše Re: Segfault pri strcpy v rekurzivni fci
    No pokud dochazi v adresarove strukture ke zmenam, je zrejme treba aktualizovat dane mapovani deskriptoru na adresar. Jak se pise v manualu inotify.
    The inotify API identifies affected files by filename. However, by the time an application processes an inotify event, 
    the filename may already have been deleted or renamed.
    
    If  monitoring  an  entire directory subtree, and a new subdirectory is created in that tree, be aware that by the time you
    create a watch for the new subdirectory, new files may already have been created in the subdirectory.  Therefore, you may
    want to scan the contents of the subdirectory immediately after adding the watch.
    
    Takze muj hrubej odhad je, ze chyba je spis ve spatny praci s inotfiy, nez ve zvolenejch strukturach. Ale jak uz bylo receno. Pouziti pole neni zrovna robustni a pouzil bych radsi hash tabulku.
    tomes.io avatar 16.1.2014 15:50 tomes.io | skóre: 12 | blog: tomesh
    Rozbalit Rozbalit vše Re: Segfault pri strcpy v rekurzivni fci
    Ano, ve finale jsem taky zjistil, ze to mapovani byla pricina. Pri MOVED_TO se nic nezaktualizovalo, zapomnel jsem na to, mel jsem to osetrene jen u CREATE, pritom MOVED_TO se musi chovat stejne.
    tomes.io avatar 16.1.2014 09:47 tomes.io | skóre: 12 | blog: tomesh
    Rozbalit Rozbalit vše Re: Segfault pri strcpy v rekurzivni fci
    Asi vyuziju spojovaci seznam, ten mi prijde momentalne nejjednodussi.
    14.1.2014 06:09 jas | skóre: 13 | blog: blag
    Rozbalit Rozbalit vše Re: Segfault pri strcpy v rekurzivni fci

    Taka poznamka mimo: Segmentation fault urcite nie je sposobeny chybnou alokaciou path, kedze asprintf si alokuje pamat sam (preto tam ide char **).

    Chyba v tej alokacii je a to ta, ze sa vobec nejaka manualna alokacia premennej path robi.

    14.1.2014 08:14 Šangala | skóre: 56 | blog: Dutá Vrba - Wally
    Rozbalit Rozbalit vše Re: Segfault pri strcpy v rekurzivni fci
    Vidíš, toho jsem si ani nevšiml, asprintf nepoužívám a man jsem nedočetl…
    To, že trpíš stihomamem, ještě neznamená, že po tobě nejdou. ⰞⰏⰉⰓⰀⰜⰉ ⰗⰞⰅⰜⰘ ⰈⰅⰏⰉ ⰒⰑⰎⰉⰁⰕⰅ ⰏⰉ ⰒⰓⰄⰅⰎ ·:⁖⁘⁙†

    Založit nové vláknoNahoru

    Tiskni Sdílej: Linkuj Jaggni to Vybrali.sme.sk Google Del.icio.us Facebook

    ISSN 1214-1267   www.czech-server.cz
    © 1999-2015 Nitemedia s. r. o. Všechna práva vyhrazena.