Registrace nového uživatele     Návod     Kluby     Archív  Lopuchu     Lopuch.cz  

Což takhle
dát si Lopuch?

Lopuch.cz

Jméno:
Heslo:
Podpora LCD:
 
Klub C, C++ [ŽP: neomezená] (kategorie Programování) moderuje Šéf Lopuchu.
Archiv

Články

Jak bezpečně ukončit vlákno z DllMain
FastAllocPool - urychlení častých alokací a dealokací
Akce a zpráva jako objekt
Tuply v C++
Efektivní alokátor malých objektů a tady druhý a třetí díl
Šablony: Být vládce kvalifikátorů
Vracíme z funkce objekty
Základy komunikace mezi procesy (ve Windows)
Multiple Interface a Instance Factory
Multithreading v C++ (ve Win32)
  Nastavení klubu     Nastavení práv     Homepage     Anketa     Přítomní     Oblíbené     Lopuch     Kategorie  
autor: 
text: 
vyplnit a 
Help
 Titulek, text příspěvku  
Opište pozpátku následující text bez prostředního znaku: shscqqw
[ 380 ] <Novější  <<<Nejnovější  Nejstarší>>>  Starší>  
sekory Sekory The journey of thousand miles - starts with a single step. 8.3.2010 15:00  811
C++ za 21 dní :-)
bredy 1.3.2010 19:45  810
DavpeNikoliv. Alokátor je objekt, který se jednoduše stará o alokace. Jeho využití je zejména u kontejnerů, kterým lze ovlivnit způsob, jak se budou alokovat prvky, nebo interní struktury kontejneru. Příklad: std::allocator

Já mám ve své knihovně dvoustupňové allokátory. První stupeň je StdAlloc, který je továrnou pro tzv. StdAllocBlock. Tenhle objekt obsahuje ukazatel na alokovaný prostor a jeho velikost. Tenhle blok lze předat třeba do AutoArray (něco jako vector) a v něm pak ten objekt alokuje. Tenhle druhý stupeň alokátoru se umí i relokovat a má tu vlastnost, že sám v destruktoru volá delete.

Mezi dalšími alokátory mám třeba StaticAlloc<n> který dělá podobnou věc jako StdAlloc, akorát alokuje vždy statické pole dané velikosti (n). Když to vrazíš do AutoArray, tak uděláš to, co s vektorem nikdy. Kontejner bude ve svým těle obsahovat rezervovaný prostor pro n prvků, ale dál se bude chovat jako rozšiřovatelné pole (až do velikosti n). Odpadne tak jedno zbytečný new a delete.

Ale abych to shrnul. Alokatorem obecně nazýváme objekt, který má na starost přidělování a uvolňování paměti. Poskytujeme ho kontejnerům, nebo dalším objektům, které něco musí alokovat. V šablonách je pak výhodou to, že můžeme kontejneru podstrčit alokátor, který třeba nealokuje paměť fyzicky, ale alokace nějakým způsobem emuluje. Nebo alokuje ve speciální haldě, třeba ve sdílené paměti.
davpe Davpe 1.3.2010 16:27  809
Bredy: alokátory? to je něco jako garbage collector?
huh huh 1.3.2010 15:20  808
Visual Studio® 2010 Express Beta 2
bredy 1.3.2010 15:16  807
Nedávno vyšlo Visual Studio 2010 RC - je to normálně volně ke stažení na webu. Nenašel jsem žádné informace o limitacích tohoto balíku. Předpokládám podobnou taktiku jako u Windows 7? Taky jsem nenašel Express edition, tedy jestli se opravdu chystá, nebo bude politika jiná? Každopádně doma vyzkouším nainstalovat a uvidíme.
bredy 1.3.2010 12:47  806
SekoryJak jsem říkal, násobení může stát víc času, než dereference adresy. Protože dva vektory v sobě není nic jiného než jednorozměrné pole ukazatelů na jednorozměrné pole. Takže vyzvednout prvek z pozice 100,150 znamená vyzvednout stý ukazatel (adresa 100 * 4) a k němu přičíst 4 * 150 (násobění 4x je posun, narozdíl od plnohodnotného násobení)
sekory Sekory The journey of thousand miles - starts with a single step. 1.3.2010 12:24  805
Zajímavý, tak když to samé zkompiluju jako release, tak je výsledek 24ms a 22ms ve prospěch přístupu přes vektory.
sekory Sekory The journey of thousand miles - starts with a single step. 1.3.2010 11:41  804
Bredy: Máš pravdu, zkoušel jsem to jen přes Debug, nenapadlo mě, že by to mohl být nějaký větší rozdíl, schválně to zkusím. Naučit bych se to mohl... takhle používám C++ více méně jako C (kde moje znalosti taky nejsou nejvýšší), takže objektové principy a podobné věci jdou mimo mě. :)

Davpe: Díky za odkaz, to už jsem taky někde četl, ale moc následků to na mě nezanechalo, když mi to v praxi nedojde.
bredy 1.3.2010 11:26  803
SekoryNetuším proč by to mělo být pomalejší. Možná si to jen překládal v Debug konfiguraci, protože tam dává STLko spoustu kontrol, jako kontroly rozsahů. U Release by ty kontroly měly odpadnout. Přístup do pole přes vektor je pak otázka dereferencí dvou adres, u prvního způsobu je zase zdržovákem to násobení. No možná tam může hrát roli výpadek stránky z cache, která u prvního způsobu vypadne v průměru méněčasto, než u druhého. Ale tak drastický by to být nemělo.

Doporučuju se každopádně naučit C++ pořádně, než se pouštět do programování čehokoliv. C++ není PHP.

Co se zásobníku týče, pokud vytvoříš proměnnou uvnitř funkce, vznikne na zásobníku. Vždycky. Ten je omezený. Vždycky. Pokud proměnnou vytvořiš dynamicky, ať už pomocí new, nebo malloc (vektor to taky alokuje newem), tak se vytvoří v separátním prostoru, zvaném halda. Halda je omezena jen dostupnou volnou pamětí (což bývá v době swapování paměti na disk víc než instalovaná pamět).

Davpe: Ano, ale na vyšší úrovni pokud možno nealokujeme. Necháváme to do těl tříd. Používáme kontejnery, a pokud už musíme něco alokovat, tak v konstruktoru a dealokovat v destruktoru. Jinde to nemá smysl (protože výjimky). A to já třeba používám alokátory, které si hlídaji alokovanou paměť a sami se postarají o její likvidaci při zániku platnosti... a to vedle chytrých ukazatelů... které dělají totéž.
davpe Davpe 1.3.2010 08:56  802
Sekory:
První ti jde bez problému, protože se paměť alokuje na halde (při používání new nebo malloc).
Ve druhém příkladě je velikost známá při překladu (jasně, v prvním příkladě sice taky, ale kdybys tam dal proměnou, která by ti velikost načítala ze vstupu, tak ti první příklad přesto pojede, protože se paměť alokuje dynamicky, kdežto druhý se nepřeloží) a tak se pole alokuje přes zásobník. Zde je to popsané (sice to je C#, ale neva)


Bredy: K té poslední větě, vždyť new musíš taky dealokovat pomocí delete ne?
sekory Sekory The journey of thousand miles - starts with a single step. 1.3.2010 02:03  801
Bredy: Moc díky tak podrobnej popis jsem nečekal. Ten přetékající zásobník nechápu... Nechápu proč statická proměnná v něm musí být celá a dynamická ne viz toto:

int *pole=new int[1000000]; //jde bezproblému
vs.
int pole[1000000]; //nahlásí chybu

přičemž s tím dále pracuji stejně. Netušil jsem, že to jde takhle jednoduše obejít. Takže asi budu používat toto, tvůj typedef sice vypadá líp, ale používal bych něco, co nevím jak funguje (std::vector a vůbec takové použití typedef je pro mě neznámá) navíc se zdá pomalejší, v mém mini testu vychází 34ms oproti 154ms:

int *pole=new int[1000000];
    srand(timeGetTime());
    unsigned long cas=timeGetTime();
       for (int i=0;i< 1000;i++) {
          for (int j=0;j< 1000;j++)
             pole[i*1000+j]=rand();
       }

       cout<<"Cas: "<< timeGetTime()-cas<< endl;
       delete []pole;

    typedef std::vector< int> RadkaPole;
    typedef std::vector< RadkaPole> CelePole;
    CelePole pol(1000,RadkaPole(1000,0));

    cas=timeGetTime();
       for (int i=0;i< 1000;i++) {
          for (int j=0;j< 1000;j++)
             pol[i][j]=rand();
       }
       cout<<"Cas: "<< timeGetTime()-cas<< endl;



No nic musím říct, že mi to takhle po nocích už moc nemyslí jdu raději spát.
bredy 1.3.2010 00:44  800
SekoryOno to v tej chybě je popsané. Stack overflow znamená, že přetekl zásobník. Zásobník je běžně u procesu nastavený na 1MB. Takže není divu, že to přeteče.

Ono totiž takhle velké "objekty" nelze dávat do zásobníku. Je nutné to alokovat. Nevím, jestli trváš na C++ nebo jen na C. V případě C++ je to jednoduché

#include <vector>

int main(int argc, char *argv[]) 
{
  typedef std::vector<int> RadkaPole;
  typedef std::vector<RadkaPole> CelePole;
  CelePole pole(1000,RadkaPole(1000,0));
  //... a tady se jede dál

}

Zápis nahoře nejprve definuje RadkaPole jako obecný vektor hodnot typu int. Druhý řádek definuje CelePole jako obecný vektor řádek (RadkaPole). Třetí řádek pak vytváří proměnnou pole a to tak, že ji inicializuje na 1000 prvků, z nichž každý prvek (což je RadkaPole) inicializuje jako 1000x hodnota 0.

Pokud bys chtěl jen čistě C, tak tam je to náročnější. Záleží na tom, jak chceš 2D pole implementovat. První varianta je ta, že je to prostě vyhrazený kus paměti, kde se prvky skládají "zleva doprava, zezhora dolu"

Pak musíš alokovat:

int *pole = (int *)malloc(sizeof(int)*1000*1000);

do pole přistupuješ přes přepočet
pole[r * 1000 + c] //kde r je řádek, c je sloupec


Jiná varianta je nadefinovat si prvek ve tvaru jednoho řádku, jako u vektoru
typedef int JedenRadek[1000];
JedenRadek *pole = (JedenRadek *)malloc(sizeof(JedenRadek)*1000);


vlastně jsi založil pole o 1000 prvků, kdy každý prvek má 1000 intů.

Další možnost je vytvoři pole o 1000 ukazatelů na jednorozměrné pole, kde budeš alokovat 1000x pole o 1000 prvků

typedef int *JedenRadek;
typedef JedenRadek *CelePole;
CelePole pole = (CelePole)malloc(sizeof(JedenRadek)*1000);
for (int i = 0; i < 1000; i++)
   pole[i] = (JedenRadek)malloc(sizeof(int) * 1000);


Nevýhodou řešení v C je nutnost každou alokaci po skončení práce dealokovat (každý malloc musí mít svůj free). V C++ tohle odpadá.
sekory Sekory The journey of thousand miles - starts with a single step. 28.2.2010 23:51  799
Můj problém je následující, chci vytvořit poměrně velké dvourozměrné pole, ale již při následujícím kódu mi to hlásí chybu:

#include "stdafx.h"

int _tmain(int argc, _TCHAR* argv[])
{
int pole[1000][1000];
return 0;
}

First-chance exception at 0x00081637 in test11.exe: 0xC00000FD: Stack overflow.
Unhandled exception at 0x00081637 in test11.exe: 0xC00000FD: Stack overflow.
The program '[2928] test11.exe: Native' has exited with code -1073741571 (0xc00000fd).


Používám Visual Studio 2010. Co mám dělat, chci-li vytvořit takhle velké pole? 1000*1000*4B jsou 4MB to mi nepříjde zase tolik. Zkoušel jsem měnit nastavení Linkeru, kde jsou položky jako "Stack Reserve Size", nicméně beze změny. Předpokládám tedy, jelikož tomuhle pranic nerozumím, že sem asi trochu vedle.
huh huh 28.8.2009 18:06  797
Kdokoliv [796]: Já ti to neberu. Já bych si kvůli tomu na krk další knihovnu nevázal. To člověk může udělat vždycky. Člověk za půl roku zjistí, že chce program zkompilovat na nějaké obskurnější platformě a tejden stráví tím, že se tam snaží rozchodit cizí knihovny, na kterejch je závislej.

Příprava předem u mě spočívá v tom, že si mezi svůj kód a cizí knihovny vložím vlastní vrstvu.
kdokoliv Kdokoliv Nevidím důvod dělat cokoliv bezdůvodně. - http://kkl2401.wz.cz 28.8.2009 17:45  796
huh [795]: Hele jak bych to rekl. Ja uz tolikrat "chtel napr. to a to" a za pul roku zjistil, ze vlastne taky jeste chci (nebo nekdo jinej chce) tamhleto a tamhleto, ze uz s tim radsi pocitam predem. :-)

[ 380 ] <Novější  <<<Nejnovější  Nejstarší>>>  Starší>  

(c) 2001-2011 Lopuch.cz   
Kontakt