Fórum Root.cz
Hlavní témata => Vývoj => Téma založeno: Onestone 19. 04. 2017, 13:26:54
-
Zdravím, potřeboval bych vysvětlit jednu podivnost. Na Linuxu používám libdispatch v kódu v C, vytvořím si čítač (int counter) a ten pak používám v blocích, které dávám do fronty. Na hlavním vlákně si chci občas přečíst hodnotu, mám tam ukazatel na counter, ale program při čtení *counter spadne. Evidentně to nějak souvisí s těmi bloky, když je fronta prázdná, kód běží. Má s touto knihovnou někdo zkušenosti?
-
P.S. Při výpisu pomocí %p je po zpracování celé fronty ta adresa čítače jiná než při deklaraci ???
-
Zdravím, potřeboval bych vysvětlit jednu podivnost. Na Linuxu používám libdispatch v kódu v C, vytvořím si čítač (int counter) a ten pak používám v blocích, které dávám do fronty. Na hlavním vlákně si chci občas přečíst hodnotu, mám tam ukazatel na counter, ale program při čtení *counter spadne. Evidentně to nějak souvisí s těmi bloky, když je fronta prázdná, kód běží. Má s touto knihovnou někdo zkušenosti?
Asi by tochtelo nekam hodit ten kod, nebo aspon ukazku. Co presne je mysleno tim lokalni promenna? Pokud je tim mysleno opravdu lokalni promenna tak na tu nedava smysl delat ukazatel a ten pouzivat nekde mimo, jelikoz to kam ten pointer ukazuje uz nemusi existovat
-
Co znamená "lokální proměnná"? Resp. jaká je úroveň toho "lokální"? Od jisté úrovně "lokálnosti" (nestatická uvnitř funkce) je vytvářena na zásobníku a po návratu z funkce má nedefinovanou hodnotu ;)
Bez ukázky kódu se ale asi nehneme...
-
Zdravím, potřeboval bych vysvětlit jednu podivnost. Na Linuxu používám libdispatch v kódu v C, vytvořím si čítač (int counter) a ten pak používám v blocích, které dávám do fronty. Na hlavním vlákně si chci občas přečíst hodnotu, mám tam ukazatel na counter, ale program při čtení *counter spadne. Evidentně to nějak souvisí s těmi bloky, když je fronta prázdná, kód běží. Má s touto knihovnou někdo zkušenosti?
Asi by tochtelo nekam hodit ten kod, nebo aspon ukazku. Co presne je mysleno tim lokalni promenna? Pokud je tim mysleno opravdu lokalni promenna tak na tu nedava smysl delat ukazatel a ten pouzivat nekde mimo, jelikoz to kam ten pointer ukazuje uz nemusi existovat
Struktura kódu je takováto:
int main() {
__block int c = 0;
printf("%p\n", &c);
dispatch_async(...);
printf("%p\n", &c);
...
}
Ty dva printfy vypisují různé adresy. Potřebuju předat jiné asynchonní knihovně ukazatel na ten čítač jako parametr (void*), proto to řeším, ale nevím, jak to udělat bezpečně, aby ten ukazatel zůstal platný. Funkce main nakonec končí ve smyčce událostí, takže proměnné na zásobníku zůstávají platné.
-
Hmmm... lokální proměnná typu int (ideálně čítač) má tendenci být alokován do nějakého volného registru. Nicméně nápad použít ukazatel na lokální proměnnou nepatří mezi "zlaté standardy" programování bez ohledu na cokoli dalšího.
-
Jenom jako pokus zkuste proměnnou c udělat:
1. globální - mimo main()
2. statickou v main()
Teorie mi říká, že by to mělo pomoci...
-
Hmmm... lokální proměnná typu int (ideálně čítač) má tendenci být alokován do nějakého volného registru. Nicméně nápad použít ukazatel na lokální proměnnou nepatří mezi "zlaté standardy" programování bez ohledu na cokoli dalšího.
V C se callbackům dává parametr typu void*, takže ukazatel na int je naprosto normální, když vím, že proměnná na zásobníku ještě bude. Jde to samozřejmě obejít explicitním mallocem a toto řešení nejspíš použiju, ale z principu bych chtěl zjistit, proč výše uvedené hapruje. Doufám, že se tu objeví nějaký profík na C a vysvětlí to, možná to je nějaká samozřejmá blbost, kterou jen nevidím.
-
nebylo by řešením jednoprvkové pole?
Možná ještě nějaké to volatile.
Optimalizace taky může pracovat s tím, že c není nikde měněno a pošle pokaždé ukazatel na nějakou nulu...
-
nebylo by řešením jednoprvkové pole?
Možná ještě nějaké to volatile.
Optimalizace taky může pracovat s tím, že c není nikde měněno a pošle pokaždé ukazatel na nějakou nulu...
Provizorně jsem to vyřešil mallocem. Ale ten čítač se mění v těch úlohách fronty, tam právě předpokládám ten problém.
-
Hmmm... lokální proměnná typu int (ideálně čítač) má tendenci být alokován do nějakého volného registru. Nicméně nápad použít ukazatel na lokální proměnnou nepatří mezi "zlaté standardy" programování bez ohledu na cokoli dalšího.
V C se callbackům dává parametr typu void*, takže ukazatel na int je naprosto normální, když vím, že proměnná na zásobníku ještě bude. Jde to samozřejmě obejít explicitním mallocem a toto řešení nejspíš použiju, ale z principu bych chtěl zjistit, proč výše uvedené hapruje. Doufám, že se tu objeví nějaký profík na C a vysvětlí to, možná to je nějaká samozřejmá blbost, kterou jen nevidím.
Odpověď je pravděpodobně poměrně jednoduchá - optimalizace. Řešení se jmenuje volatile. Ale upřímně, raději bych tu proměnnou viděl jako lokální v modulu a navíc static a volatile.
-
Řekl bych, že procedura main nečeká na dokončení funkce display_async.
-
Řekl bych, že procedura main nečeká na dokončení funkce display_async.
Čeká, už jsem psal, že uvízne ve smyčce událostí. A i kdyby ne, tak ty adresy se vypisují ještě v mainu.
-
Liší se výsledek mezi různými hodnotami přepínače -On?
-
Liší se výsledek mezi různými hodnotami přepínače -On?
Ne. Při vývoji to překládám bez optimalizací, ale různé -On na to nemají vliv, teď vyzkoušeno.
-
Struktura kódu je takováto:
int main() {
__block int c = 0;
printf("%p\n", &c);
dispatch_async(...);
printf("%p\n", &c);
...
}
Ty dva printfy vypisují různé adresy. Potřebuju předat jiné asynchonní knihovně ukazatel na ten čítač jako parametr (void*), proto to řeším, ale nevím, jak to udělat bezpečně, aby ten ukazatel zůstal platný. Funkce main nakonec končí ve smyčce událostí, takže proměnné na zásobníku zůstávají platné.
Jak je přesně definovaný modifikátor __block na linuxu? Co to dělá?
-
určitě je to lokální proměnná? https://en.wikipedia.org/wiki/Blocks_(C_language_extension)
-
Zdravím, potřeboval bych vysvětlit jednu podivnost. Na Linuxu používám libdispatch v kódu v C, vytvořím si čítač (int counter) a ten pak používám v blocích, které dávám do fronty. Na hlavním vlákně si chci občas přečíst hodnotu, mám tam ukazatel na counter, ale program při čtení *counter spadne. Evidentně to nějak souvisí s těmi bloky, když je fronta prázdná, kód běží. Má s touto knihovnou někdo zkušenosti?
Asi by tochtelo nekam hodit ten kod, nebo aspon ukazku. Co presne je mysleno tim lokalni promenna? Pokud je tim mysleno opravdu lokalni promenna tak na tu nedava smysl delat ukazatel a ten pouzivat nekde mimo, jelikoz to kam ten pointer ukazuje uz nemusi existovat
Struktura kódu je takováto:
int main() {
__block int c = 0;
printf("%p\n", &c);
dispatch_async(...);
printf("%p\n", &c);
...
}
Ty dva printfy vypisují různé adresy. Potřebuju předat jiné asynchonní knihovně ukazatel na ten čítač jako parametr (void*), proto to řeším, ale nevím, jak to udělat bezpečně, aby ten ukazatel zůstal platný. Funkce main nakonec končí ve smyčce událostí, takže proměnné na zásobníku zůstávají platné.
Když padá kód bez zjevné chyby, hodíme to na překladač. Někde v dispatch_async se volá Block_copy (kvůli zařazení do fronty), což obnáší kopii kontextu bloku ze zásobníku na haldu. Neměnitelné lokální proměnné se klonují, měnitelné se přealokují na haldě. Celé to řeší překladač a runtime, v knihovnách nic není. Taky pozor na to, že po posledním Block_release ta proměnná zmizí (automaticky se dealokuje). Ono to je celé trochu magie a __block je lepší nepoužívat.
-
určitě je to lokální proměnná? https://en.wikipedia.org/wiki/Blocks_(C_language_extension)
Je lokální až do zavolání Block_copy, jenže když to dělá knihovna, tak člověk neví, co se kdy děje. Aspoň to ale funguje lépe než v C#.
-
Takové starosti bych chtěl mít, zlatá Java...