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 »Doba kompilace linuxového jádra se díky rychlejšímu hardwaru a optimalizacím kbuildu snižuje k deseti sekundám. Nejnovější patche Lorenza Stoakse (vznikají i s pomocí SI) zkrátily na testovacím stroji dobu sestavení z dlouhých 22 vteřin na pouhých 15, a to bez použití RAMdisku. Testovací systém tvořily dva procesory AMD EPYC 9575F (oba dohromady poskytují celkem 128 jader a 256 vláken), čtyřiadvacet 64GB DDR5-6400 paměťových modulů a
… více »Před rokem a půl vývojáři postmarketOS informovali, že pro projekt hledají nové jméno. Včera bylo oznámeno: postmarketOS se nově jmenuje Nura.
Hra Factorio dorazila na Printables. Hned teď si můžete stáhnout 65 různých modelů a nechat celou mimozemskou planetu oživnout na svém stole.
GNU Project Debugger aneb GDB byl vydán ve verzi 18.1. Podrobný přehled novinek v souboru NEWS.
Prezident USA Donald Trump během svého projevu na valném shromáždění OSN 22. září 2026 prohlásil, že umělá inteligence 'bude dále oficiálně nazývána superinteligencí', zkráceně SI. Svůj návrh zdůvodnil takto: 'Použití slova artificial činí inteligenci falešnou. Ona falešná není, ve skutečnosti je úžasná'. Zároveň ve svém proslovu prohlásil, že Spojené státy kategoricky odmítají jakékoliv pokusy o vytvoření 'globalistického
… více »Čínská technologická firma Xiaomi představila novou verzi 2.6 svého modelu MiMo, váhy modelů MiMo‑V2.6‑Pro‑RL a MiMo‑V2.6‑Flash‑RL jsou dostupné na HuggingFace pod licencí MIT. Výkonnější varianta Pro má přes bilion parametrů, z toho 42 miliard aktivních, úspornější Flash 309 miliard parametrů, z nichž se při generování aktivuje přibližně 15 miliard. Oba modely mají délku kontextového okna milion tokenů. Tyto MoE modely zvládají
… více »Proběhl Snapdragon Summit 2026. Společnost Qualcomm se mimo jiné pochlubila během Linuxu na čipech Snapdragon X2. Zatím pouze v ranní verzi vhodné pro vývojáře linuxových distribucí a přispěvatele do jádra Linux.
Byla vydána nová verze 2.0 klienta F-Droid určeného pro instalaci bezplatných a otevřených mobilních aplikací do Androidu ze softwarového repozitáře F-Droid (Wikipedie). Jedná se o alternativu k Google Play.
#ifndef SORTING_H #define SORTING_H char **alloclines(int n); char **realloclines(char** memold, int *nold); int cmp(char *s1, char *s2); int readline(char *l); void freelines(char **l, int n); void print(char **l, int n); #endifSprav, nech načítava ne do prázdneho riadku, ale dokiaľ je vstup. Vstup ukončíš v konzole CTRL + D. ...
if(fgets(...) == NULL)
{
// vstup bol ukončený
}
A funkciu main dávaj nakoniec v súbore (alebo najdôležitejšiu funkciu, ak tam nie je main v zdrojovom kóde). Taký nejaký profesionálnejší štandard.
A ďalšia poznámka. Neplytvaj pamäťou. Tj. alokuj pamäť na riadok, až keď budeš mať riadok načítaný. Vtedy vieš jeho veľkosť, a miesto MAXLINE alokuješ reálnu veľkosť.
A použi štruktúru (dátový typ), popíš ňou riadky a s ňou pracuj. A aj tú daj na spracovanie funkciám ako parameter. To potom bude krása.
A keď chceš profesionálnejšie, tak aj testuj stupy pre funkcie. Chyba je NULL, a co ak všade pošlem napr. pre char **realloclines(char** memold, int *nold) ako memold NULL alebo *NULL;
.h soubor pouze pro main.c opravdu moc nemá moc smysl. .h soubor má smysl, pokud ho bude někdo includovat, nejlépe více souborů než jen main.c
Tvoj program skoro robí ako príkazy # cat | sortIf you hold a UNIX shell up against your ear. Can you hear the C? :-)
Tvoj program skoro robí ako príkazy # cat | sort A ďalšia poznámka. Neplytvaj pamäťou. Tj. alokuj pamäť na riadok, až keď budeš mať riadok načítaný. Vtedy vieš jeho veľkosť, a miesto MAXLINE alokuješ reálnu veľkosť.Jednoduché řešení je mít samostatný buffer pro vstup a v okamžiku, kdy je řádek načtený, tak ho vykopírovat na čílové místo něčím na způsob
strdup(), takže se použije jen tolik paměti, co je třeba. Onen vstupní buffer může být ve většině případů dokonce staticky alokovaný, případně dynamicky alokovaný na určitou předem nastavenou velikost, protože pokud nepotřebujeme neomezeně dlouhé řádky, je jednodušší řešení nesmyslně dlouhé řádky zahazovat (k čemu je např. konfugurační soubor, z jehož čtení nám půjdou oči šejderm a při jehož editaci se uscrollujeme k smrti
) .
No a pokud je třeba dynamická alokace, tak nemá smysl zvyšovat velikosti po jednotkách byte, minimální granularita většiny implementací hald je většinou kolem šestnácti byte a pokud se paměť opravdu přidává, tak je to minimálně o velikosti jedné stránky (4KB na x86 a běžných ARMech, dá se zjistit dynamicky přes getpagesize() nebo sysconf()). Když už, tak zvětšovat právě o velikost stránky nebo něco strovnatelného.
Mimo toho, že se ušetří čas, kderý by se zbytečně trávil managementem haldy (bez toho, že by zavolal sbrk()), to má vliv i na nižší fragmentaci haldy, obzvlášť pro pesimální případy, kde délka řádku monotóně roste s jeho pozicí (takže nelze znovu použít uvolněné "díry" v haldě).
PS: Když se toto alokuje opravdu, ale opravdu hodně (IIRC, limit je 128MB u GNU libc), tak malloc() a spol. začnou požívat místo haldy přímé mapování anonymní paměti pčes mmap() (tedy, v unixech, jask se to dělá ve Windows, nemám potuchy). Osobně si myslím, že pak je lepší se na paměťový management přes malloc() a spol. vykvajznout a buď použít nějaký lepší alokátor, nebo si to dělat ručně právě přes malloc(), což má navíc výhodu v tom, že můžeme mnohem přesněji ovlivnit, jak se s pamětí nakládá (přes madvise())nebo kdy se paměť uvolní (nutné, když jednu chvíli potřebujeme spoustu paměti a v té náskledujcí jí musíme zase uvolnit pro někoho jiného).
IIRC, limit je 128MB u GNU libcMoje mallopt(3) říká, že ten limit je 128 KiB.
tak malloc() a spol. začnou požívat místo haldy přímé mapování anonymní paměti pčes mmap()Python (resp. CPython) dělá něco takového taky. Debugování memory leaků je pak výborný :-/
>>> import kerberos
>>> kerberos.authGSSClientInit("HTTP@krbhost.example.com")
(1, <PyCObject object at 0x7f56004e65d0>)
>>>
Ano, muze za to kerberos modul napsany v C, ale hadam ze debugovani python C extensions mel prave kralyk na mysli.
Měmory leak v Pythonu? Wtf?Python-C interop. Céčková strana naalokuje nějaké pythonní objekty a neuvolní je. Tyhle objekty můžou bejt naalokovaný přes malloc, ale někdy taky přes mmap (zcela bez volání mallocu). Nástroje jako valgrind a podobně tohle nedohledají. Nakonec jsem to řešil trasováním mmap syscallu a koukal na backtraces, abych zjistil, odkud se to alokuje. Možná existuje chytřejší způsob.
Jasně. Jak výše vyplynulo, leakuje nějakej c bazmek, ale může za to Python.Tenhle čistě pythonní kód u mě sežere ~1GB RAM:
#!/usr/bin/env python2
import sys
class Foo(object):
def __init__(self, other=None):
self.other = other
def __del__(self):
pass
if __name__ == "__main__":
for i in range(1000000):
foo = Foo()
bar = Foo(foo)
baz = Foo(bar)
foo.other = baz
sys.stdin.readline()
(V Pythonu 3 mi to nejde reprodukovat, proto then python2)
Jinak ale leaky jdou vytvořit i bez triků s __del__, viz třeba tenhle kód:
#!/usr/bin/env python3
import sys
foobar = []
def avg_line_length(file):
avg = len(file.readline())
if avg == 0:
return 0
else:
avg -= 1
n = 1
for line in file:
n += 1
avg = avg + (len(line) - 1 - avg) / n
foobar.append(line)
return avg
if __name__ == "__main__":
print(avg_line_length(sys.stdin))
sys.stdin.readline()
Tady je sice hodně zřejmý, kde a proč to leakuje, ale jakmile budeš mít nějakou větší codebase ve který bude podobný problém zašmodrchaný a rozetřený přes X modulů, už nebude tak snadný to dohledat.
Tož tak.
Já tomu python3 kódu moc nerozumím, ale za ten leak považuješ ten foobar?Jj. Kvůli němu má ten program lineární paměťovou složitost místo konstantní.
foobar v tom prográmku výše není k ničemu potřeba, ale GC to nepozná. Být to v nějakém jazyce s nějakým chytrým kompilátorem, mohl bys dostat warning, něco jako "Value assigned to foobar is never used" nebo podobně...
A ano, to, jestli program nějaký resource potřebuje, může být věc názoru. Např. v některých C/C++/apod. programech jsou objekty, který se jednou naalokujou a záměrně nikdy neuvolní. Valgrind to může označit za leak, ale přitom programátor to za leak nepovažuje.
Být to v nějakém jazyce s nějakým chytrým kompilátorem, mohl bys dostat warning, něco jako "Value assigned to foobar is never used" nebo podobně...Nevím, jak u pole, ale u obecného objektu dost těžko – máš totiž nějakou instanci a na ní voláš nějakou metodu (
append) a jestli tu instanci pak někam přiřadíš nebo s ní uděláš něco jiného je jedno – ta užitečnost mohla spočívat v tom, že jsi volal tu metodu a instance na základě toho něco dělala.
leakuje nějakej c bazmek, ale může za to Python.Za leak může C bazmek, to je bez debat. Za to, že ten leak šel blbě dohledat nicméně může CPython, protože se snaží bejt chytrej a používat vlastní alokační fígle s
mmap(). Jak moc jsou tyhle fígle užitečný, to nevim, možná jsou, ale mám svoje pochybnosti...
int pro účel velikosti něčeho v paměti. Velikost toho typu může být nedostatečná, nebo naopak příliš velká. Používej typ size_t. Funkce jako malloc, calloc, realloc, všechny mají parametr typu size_t. Funkce qsort taky očekává parametry typu size_t. Používáním intu se můžeš dopustit závažných chyb, např. přetečení a následné předání špatné velikosti daným funkcí, kvůli konverzím.
2) Pokud funkce realloc selže, původní buffer není uvolněn. Máš tam možný memory leak ... sice hned voláš exit(), ale může tě to naučit špatným zvyklostem, třeba až takovou kontrolu někdy dáš do nějaké vlastní knihovny, co ukončovat program nebude.
3) Komparátor funkce qsort má typ int (*)(const void *, const void*). Tvůj má úplně jinou signaturu. To přetypování je hnus, nejsem si jistý, ale asi se dokonce bude jednat i o UB, teoreticky by ty funkce nemusely být volatelné stejným způsobem. A obzvláště, když v tom komparátoru stejně přetypováváš, tak můžeš nechat signaturu správně.
4) Dynamická alokace je většinou od toho, abys nemusel mít nějaký fixně veliký buffer, což stejně pro jednotlivé řádky máš. Jednotlivé řádky bych alokoval až poté, co ho přečteš.
5) Asi je zbytečné mít extra funkci pro realokaci, funkci realloc můžeš předat NULL jako první parametr a bude se chovat jako malloc. Stačí inicializovat proměnnou předem na NULL a nemusíš pak mít 2 funkce, co dělají to samé.
6) Ukazatele (kromě ukazatelů na funkce) jsou implicitně přetypovatelné na void*, netřeba přetypovávat, pokud voláš funkci free(). void* ukazatele jsou implicitně přetypovatelné na ukazatele na jiné (platí pouze v C, v C++ to neplatní).
Tiskni
Sdílej: