Hlavní navigace

GLib: Bleskové operace s pamětí (3)

16. 5. 2000
Doba čtení: 3 minuty

Sdílet

V minulých dílech jsme si ukázali, jak s knihovnou GLib urychlit alokace paměti použitím tzv. Memory Chunks. Dnes se zaměříme na využití tohoto mechanizmu při dynamické alokaci řetězců.
GMemChunk

y jsou jistě v mnoha případech užitečné. Jejich problém však spočívá v tom, že všechny prvky (atomy) musí být stejné velikosti. Tím se vylučuje použití Chunků při práci s řetězci, protože každý řetězec může být obecně proměnné délky.

Tento nedostatek vyplňuje knihovna GLib funkcemi kolem datového typu GStringChunk. Než se pustíme do dalšího výkladu, připomeňme jen v krátkosti použitou terminologii. „Chunkem“ nazývám úsek paměti, skládající se z několika bloků stejné velikosti. Do něj se pak místo alokace dynamicky umisťují nové proměnné, prvky Chunku zvané „atomy“ (viz. předchozí díl).

GStringChunk

GStringChunk 

Do GStringChunk u je možno přidávat řetězce různé délky. Není však možno jednotlivé řetězce z Chunku dealokovat – musíte dealokovat vždy celý GStringChunk.

Struktura:

struct GStringChunk; 

reprezentuje řetězcový Chunk. Práce s ní by měla být realizována výhradně následujícími funkcemi.

GStringChunk* g_string_chunk_new(gint size); 

…vytvoří nový GStringChunk a vrátí pointer na něj. Argument size je implicitní velikost bloku. Je-li třeba do GStringChunk u u­ložit řetězec delší než tato implicitní hodnota, bude pro něj alokován větší blok paměti.

Pro vkládání (neboli kopírování) řetězců do chunku slouží dvě funkce:

gchar* g_string_chunk_insert(GStringChunk *chunk,
                             const gchar *string);

a

gchar* g_string_chunk_insert_const(GStringChunk *chunk,
                                   const gchar *string);

Funkce g_string_chun­k_insert() přidá kopii řetězce string do GStringChunk u chunk. Vrátí pointer na tuto kopii. Znaky vráceného řetězce mohou být měněny. Neměli byste však, jako obvykle, zapisovat za konec tohoto řetězce.

Oproti ní, funkce g_string_chunk_insert_const() nejprve prohledá GStringChunk chunk na výskyt řetězce string. Nalezne-li takový, a byl-li do chunk u navíc přidán právě funkcí g_string_chunk_insert_const(), vrátí pointer na něj. Jinak string do chunk u zkopíruje a vrátí pointer. Tato funkce je užitečná v případech, kdy hodláte do GStringChunk u při­dávat mnoho konstantních řetězců a nechcete příliš plýtvat místem. Budete-li používat výhradně g_string_chunk_insert_const(), vloží se každý řetězec do GStringChunk u pou­ze jednou – v dalších pokusech se bude vracet pouze pointer na tento již uložený řetězec. Na to však musíte pamatovat. V programu se může vyskytovat několik pointerů na jeden řetězec – jakýkoliv zápis do takového řetězce musí být potom proveden velmi opatrně.

Je třeba poznamenat, že g_string_chunk_insert_const() nikdy nevrátí pointer na řetězec, který byl do GStringChunk u při­dán funkcí g_string_chun­k_insert(), i kdyby se shodovaly.

g_string_chunk_insert() 
void g_string_chunk_free(GStringChunk *chunk); 

…uvolní veškerou paměť alokovanou GStringChunk em chunk. Po vykonání této funkce již není bezpečné přistupovat k řetězcům, které původně obsahovala.

Příklad:

/* ukazka pouziti GStringChunk */
#include<glib.h>
gint main(void)
{
  GStringChunk *chunk;
  gchar *s1, *s2, *s3;

  /* vytvoreni noveho chunku */
  chunk = g_string_chunk_new(50);

  /* vkladani retezcu do chunku */
  s1 = g_string_chunk_insert(chunk, RETEZEC);
  s2 = g_string_chunk_insert_const(chunk, RETEZEC);
  s3 = g_string_chunk_insert_const(chunk, RETEZEC);

  /* Po techto operacich budou v chunku dva retezce "Ahoj svete!" */
  /* Na prvni bude ukazovat s1 a na druhy s2 a s3 spolecne (viz   */
  /* nasledujici vypis adres)                                     */

  printf("Adresa s1: %p\nAdresa s2: %p\nAdresa s3: %p\n", s1, s2, s3);

  /* uvolneni GStringChunku z pameti */
  g_string_chunk_free(chunk);

  return(0);
}

Po spuštění tohoto ukázkového programu by se měly vypsat adresy tří řetězců uložených do chunku. Adresa prvního řetězce by se měla od ostatních dvou lišit; adresy druhého a třetího řetězce však musí být stejné. Jak je to možné?

Všechny tři řetězce obsahují stejný text definovaný makrem RETEZEC. První řetězec, s1, se do chunku přidává jako první a navíc funkcí g_string_chun­k_insert()  – kopírování jistě proběhne.

ict ve školství 24

Po něm se alokuje řetězec s2, ovšem funkcí g_string_chunk_insert_const()  – provede se prohledání chunku na řetězec RETEZEC, ale bezvýsledně: žádný takový do chunku funkcí g_string_chunk_insert_const() ještě přidán nebyl (je lhostejné, že už tam ve skutečnosti je alokovaný funkcí g_string_chun­k_insert()).

Nakonec se alokuje řetězec s3. Voláním funkce g_string_chunk_insert_const() se znovu prohledá celý chunk – tentokrát se však nalezne řetězec s2. Funkce tento pointer vrátí – s3 tedy bude ukazovat na fyzicky stejný řetězec jako  s2

Autor článku

Michal Burda vystudoval informatiku a aplikovanou matematiku a nyní pracuje na Ostravské univerzitě jako odborný asistent. Zajímá se o data mining, Javu a Linux.