Jestem głównie zainteresowany żywotnością zmniejszanie takiej tablicy.Czy użycie realloc() na dynamicznie przydzielonej macierzy 2D jest dobrym pomysłem?
Pracuję nad projektem, w którym używałem pojedynczych wywołań malloc() do tworzenia pojedynczych średnich tablic 2D. (Co najwyżej kilkadziesiąt MiB, na największym.) Chodzi o to, że w ciągu życia jednej z tablic, jego zawartość dramatycznie się zmniejsza (o ponad połowę). Oczywiście mogłem po prostu zostawić rozmiar tablicy sam przez całe życie programu. (Jest to tylko x x MiB w systemie z dostępnym GiB RAM.) Ale, mówimy o ponad połowie przydzielonej przestrzeni, która zapada w pamięć, zanim program się zakończy i ze względu na naturę tego, w jaki sposób jestem przy użyciu tablicy wszystkie zachowane dane są przechowywane w ciągłym zestawie rzędów (na początku bloku). Wygląda na to, że marnowanie czasu na utrzymanie całej pamięci RAM, jeśli naprawdę tego nie potrzebuję.
Podczas gdy wiem, że realloc() może służyć do zmniejszania dynamicznie tworzonych tablic, tablica 2D jest bardziej złożona. Myślę, że rozumiem jego układ pamięci (jako że zaimplementowałem funkcję, która je strukturuje), ale to przesuwa granice mojej znajomości języka i działania jego kompilatorów. Oczywiście, musiałbym pracować z wierszami (i radzić sobie ze wskaźnikami wiersza), a nie tylko bajtami, ale nie wiem, jak przewidywalny byłby rezultat tego wszystkiego.
I tak, potrzebuję utworzyć tablicę z pojedynczym malloc(). Przedmiot ma kilka milionów wierszy. Próbowałem użyć pętli do malloc() każdego wiersza osobno, ale program zawsze zamarzał przy około 100 000 malloc() s.
Na tle źródło Używam skonstruować tablicę te przedstawia się następująco:
char ** alloc_2d_arr(int cnum, int rnum) {
/* ((bytes for row pointers + (bytes for data)) */
char **mtx = malloc(rnum * sizeof (char *) + rnum * cnum * sizeof (char));
/* Initialize each row pointer to the first cell of its row */
char *p = (char *) (mtx + rnum);
for (int i = 0; i < rnum; i++) {
mtx[i] = p + i * cnum;
}
return mtx;
}
'realloc' nie jest dobrym pomysłem na takie duże stoły, spójrz na drzewa" avl "i" czerwono-czarne ". –
"Wygląda na to, że marnowanie czasu na utrzymanie całej pamięci RAM, jeśli naprawdę tego nie potrzebuję." - Pierwszy * profil *.Po drugie, realloc wiąże się z wysokim ryzykiem wywołania kopiowania wszystkich Twoich wewnętrznych danych na różne strony, których niebagatelne wydatki ponoszą tylko dlatego, że próbują oszczędzać pamięci RAM, ale nie stanowi to problemu. Jedynym scenariuszem wygrywającym tutaj jest 'realloc' zachowujący tę samą głowę regionu co twoja baza pamięci, a strony końcowe są zwracane do innego użytku; coś 'realloc' nie ma gwarancji na temat ... – WhozCraig
... więc zamiast tego rozważałeś zrobienie 2 (lub 3 lub 4 dowolnych) alokacji, pamiętaj, które z nich ostatecznie przechowujesz, i' free() '- tych, których już nie potrzebujesz, gdy wydarzenie to się wydarzy? To znaczy. "zachowana" połowa twojej macierzy jest w pierwszej alokacji, druga połowa jest w innej alokacji, a ostatecznie po prostu uwolnisz drugą połowę. – WhozCraig