Edison Design Group po více než 30 letech zveřejnil zdrojový kód svého EDG C/C++ front-endu. Ten proslul širokou podporou standardů C++ a kompatibilitou s dialekty kompilátorů od Microsoftu, GNU, Clangu, Sunu a dokonce i s prehistorickým cfrontem. EDG byl použit například v kompilátoru Intel C++ Classic, kompilátoru NVCC od firmy NVIDIA pro platformu CUDA nebo v našeptávači kódu IntelliSense v produktech společnosti Microsoft. Projekt nyní spravuje organizace The C++ Alliance a kód je dostupný pod licencí Apache 2.0, doplněnou o výjimky projektu LLVM.
Pocket Tank je malé kapesní virtuální akvárium postavené na vývojové desce ESP32-S3-Touch-AMOLED-1.8. Na dvoujádrovém mikrokontroléru ESP32-S3 s 8 MB PSRAM a 16 MB flash paměti běží jak simulace akvária, tak i malý jazykový model určující chování rybiček. Lokální model o velikosti 7,56 MB se 14 miliony parametrů vznikl destilací modelu Gemma 4 26B, tedy učitele s 26 miliardami parametrů. Kromě firmwaru pro skutečný modul s AMOLED
… více »Open-source nástroj Jevstiller vytváří (destiluje) malý lokální model, který se průběžně učí z odpovědí komerční služby Jev. Běžné dotazy vyřizuje přímo na vlastním hardware, čímž může řádově zkrátit čas odezvy a snížit provozní náklady díky menšímu využívání zpoplatněného API. Nejisté požadavky Jevstiller posílá do Jevu, rovněž průběžně kontroluje náhodná dvě procenta dotazů Jevem. Pokud se lokální model začne s Jevem rozcházet,
… více »Konference LinuxDays 2026 proběhne již tento víkend 3. a 4. října v Praze v areálu ČVUT v Dejvicích na FIT. Konference LinuxDays 2026 znamená desítky přednášek a workshopů, zástup zajímavých osobností, místo pro setkání, spoustu nových nápadů a informací a stánky řady různých projektů: Fedora, openSUSE, vpsFree.cz, Mozilla, MacGyver - bastlíři SH, OpenAlt a mnoho dalších. Vstup je volný.
Microsoft oznámil, že WSL kontejnery (WSLC) aneb linuxové kontejnery ve Windows Subsystem for Linux (WSL) jsou již obecně dostupné. Současně popsal jejich architekturu.
openSUSE Leap 16.1 vstoupil do RC fáze. Nově lze instalovat jako standardní systém (Standard) nebo jako neměnný systém s atomickými aktualizacemi (Immutable). Samostatná neměnná distribuce openSUSE Leap Micro končí.
Byl vydán Mozilla Firefox 157.0. S nejvýraznější vizuální proměnou za poslední roky. Přehled novinek v poznámkách k vydání a poznámkách k vydání pro vývojáře. Řešeny jsou rovněž bezpečnostní chyby. Nový Firefox 157 bude brzy k dispozici také na Flathubu a Snapcraftu.
Rodina produktů Raspberry Pi se rozšířila o Raspberry Pi Smart Display Module. Deska pro Raspberry Pi Compute Module 5 se zasouvá přímo do displejů dle specifikace Intel SDM. Cena desky je 30 dolarů.
Byla vydána nová verze 2.56.0 distribuovaného systému správy verzí Git. Přispělo 104 vývojářů, z toho 39 nových. Přehled novinek v příspěvku na blogu GitHubu a v poznámkách k vydání.
Hackerská skupina ShinyHunters oznámila průnik do informačních systémů FBI, prostřednictvím zero-day zranitelnosti v platformě Oracle PeopleSoft, kterou úřad využívá mimo jiné pro náborový portál FBIJobs.gov. Útočníci tvrdí, že získali až 3 TB dat o současných i bývalých zaměstnancích a uchazečích o práci. Jako důkaz zveřejnili vzorek přibližně 5 000 záznamů obsahující jména, adresy, telefonní čísla, data narození, čísla
… více »
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:
path = (char *) malloc((strlen(file) + strlen(data->d_name) + 2) * sizeof (char));
Pravidlo: „Když nevíš, závorkuj.“ 
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...“
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?
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")
…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íží.
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í.
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?
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-swp256 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?
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.
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.
asprintf nepoužívám a man jsem nedočetl…
Tiskni
Sdílej: