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 ???
Citace od: Onestone kdy 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?
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...
Citace od: Danek kdy 19. 04. 2017, 14:47:22
Citace od: Onestone kdy 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?
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...
Citace od: Michal Kovačič kdy 19. 04. 2017, 15:17:04
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...
Citace od: prezek kdy 19. 04. 2017, 15:31:48
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.
Citace od: Onestone kdy 19. 04. 2017, 15:29:32
Citace od: Michal Kovačič kdy 19. 04. 2017, 15:17:04
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.
Citace od: Ivan Nový kdy 19. 04. 2017, 15:40:36
Ř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?
Citace od: hu kdy 19. 04. 2017, 15:51:27
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.
Citace od: Onestone kdy 19. 04. 2017, 15:15:01
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)
Citace od: Onestone kdy 19. 04. 2017, 15:15:01
Citace od: Danek kdy 19. 04. 2017, 14:47:22
Citace od: Onestone kdy 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?
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.
Citace od: v kdy 19. 04. 2017, 16:18:14
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...