new[]/delete[] - (n po k) elementow

0

W programie wielokrotnie w pewnej pętli mam na początku pętli:
x=new int[silnia(x*i)]
no a na końcu:
delete []x;

Po prostu w zmiennej x są dane o różnej wielkości podczas każdej literacji "i" i stąd pomysł by dynamicznie alokować na początku blok, na końcu zwalniać i tak w każdej literacji.
Problem polega na tym, że nie może być na końcu pętli delete[]x bo Visual wyrzuca CZASEM błąd w trakcie wykonywania programu w zależności jakie dane, czasem lubi wyrzucić błąd. No więc, żeby NIGDY nie wyrzucał błędu to wywaliłem z końca pętli delete []x i program działa ZAWSZE OK. I mam pytanie wobec tego co dzieje się z pamięcią, której nie zwalniam? Czy jak wyjdę z programu to te śmieci są gdzieś w komputerze? Czy tylko na czas pracy programu one są, a jak się wychodzi z programu to wszystkie niepozwalniane bloki pamięci i tak są zwalniane????

0

To jak dać formułę, że jak wskaźnik wskazuje na jakiś blok to zwolnij miejsce, a jak nie wskazuje to nie zwalniaj, bo chyba u mnie na końcu pętli o to chyba chodzi, że raz na jakiś czas zdarzy się, że blok nie zawiera żadnych danych a próbuje zwolnić i może tego Visual się czepia, nie wiem sam, w każdym razie czegoś takiego potrzebuje:
if(x!=NULL)
delete []x;

To powyżej nie działa, bo i tak Visual błąd daje w trakcie wykonywania programu.

0

Obczaiłem, że jak tablica x zawiera 1 element to wtedy Visual wywala błąd przy
delete []x.
Więc jak dać uniwersalnie zwalnianie pamięci dla x??

0

Czyli potrzebuję coś takiego:
if(x!=NULL)
{
if(x zawiera 1 element)
delete x;
else
delete []x;
}

i wtedy byłoby ok:)

0

a czemu nie skorzystasz z vector<int>??

0

bo ponoć wolniejsze od zwykłych.

0

Tak, twórcy biblioteki standardowej nie potrafili porządnie napisać dynamicznej tablicy, my potrafimy lepiej...
Jaki to błąd? Ja się założę, że bazgrzesz po pamięci...

0

Mam funkcję silnia:

unsigned int silnia (unsigned int i)
{
   if(i==0)
      return 1;
   else
      return i*silnia(i-1);
}

Właśnie wykryłem w debugerze, że problem z pamięcią wynika z tego, że ta instrukcja źle działa:
unsigned int n_po_k=silnia(n)/((silnia(n-k)*silnia(k))
np. dla
n=6, k=3 n_po_k wynosi 14 a powinno wyjść 20!
Jak więc zapisać dobrze tą linijke:
unsigned int n_po_k=silnia(n)/((silnia(n-k)*silnia(k))

0

Wychodzi tyle, ile ma wyjść - unsignedowi kończy się zakres.

0

To co dać zamiast unsigned int, bo ile unsigned int może maks pomieścić, ok 32 miliardów????

0

unsigned int : 4 294 967 296
a unsigned long long da ci 18 446 744 073 709 551 615
ale to nadal jest mało, bo zmieścisz tam tylko bardzo niskie silnie, moze pochwal sie co chcesz zrobić? Bo z reguły można te silnie poupraszczać wcześniej bez ich wyliczania...

0

potrzebuje zarezerwować n_po_k bloków pamięci i stąd potrzebne jest mi to n_po_k. Wzór na n_po_k jest:
n!/((n-k)!k!)
Jakby go uprościć to by było:
(n-k+1)
(n-k+2)...(n-k)/k!
więc już odchodzi to wielkie n! ale nie wiem jak coś takiego zaprogramować.

0

no tak bo zamknęli wikipedię
http://pl.wikipedia.org/wiki/Symbol_Newtona
gdzie masz napisane jak nalezy liczyć symbol newtona w sposób iteracyjny i rekurencyjny nie angażując w to takich wielkich liczb... Ale po co myśleć, lepiej walić brute-force i szukać większych zmiennych liczbowych :D

0

a ja bym zrobił to zupełnie inaczej. Alokowanie pamięci i jej zwalnianie jest dość czasochłonne więc nie lepiej zrobić tak (alokacja poza pętlą):

const int maxPentli = 50;
x=new int[silnia(maxPentli-1)]; // co to ma być: silnia(x*i) silnia ze wskaźnika?
for(int i=0;i<maxPentli;++i)
    {
    .....
    }
delete [] x;

Po co ciągle zwalniać i przydzielać, nie ma to uzasadnienia. poza tym nie będziesz musiał liczyć tej silni wielokrotnie.

0
winerfresh napisał(a)

Nie, zostają one w pamięci i zajmują tam miejsce.

Nie! Nie zostają w pamięci i nie zajmują tam miejsca.
OS taki głupi nie jest. Wie, które bloki pamięci przydzielił danej aplikacji, podobnie jak wie, które pliki zostały otwarte.
Po wyjściu z aplikacji posprząta. Ba, zresztą nawet niekoniecznie dopiero po wyjściu - w trakcie pracy, jeśli zacznie brakować pamięci po prostu zeswapuje zgubioną pamięć na dysk (na wypadek, jakbyś jednak tam jakiś wskaźnik do niej sobie zostawił), a pamięć fizyczną odda innym aplikacjom. ;-P

0

A masz 5.532291325*10^50 TB RAMu?

0

Nie. Po przekroczeniu pewnej granicy OS traci cierpliwość i sięga do mocniejszych argumentów. Np. Linuksie wkracza niesławny OOM killer. Z killerem jak wiadomo nie ma żartów. ;-)

0
  1. to jest nieistotny offtop
  2. on odnosił się do mojego kodu (strzeliłem liczbę 50 z sufitu i dlatego pytał się o wielkość RAMu)
0
Shalom napisał(a)

no tak bo zamknęli wikipedię
http://pl.wikipedia.org/wiki/Symbol_Newtona
gdzie masz napisane jak nalezy liczyć symbol newtona w sposób iteracyjny i rekurencyjny nie angażując w to takich wielkich liczb... Ale po co myśleć, lepiej walić brute-force i szukać większych zmiennych liczbowych :D

Aha czyli nie używac funkcji silnia() tylko np. funkcję taką:

long unsigned int licz_n_po_k(unsigned int n, unsigned int k)
{
unsigned short int i;
long double wynik=1.0;
for(i=n-k+1;i<=n;i++)
   wynik=wynik*i;
for(i=2;i<=k;i++)
   wynik=wynik/k;

return((long unsigned int)wynik);
}
}
0

Czy ty czytać wiki nie potrafisz? Tam podana jest inna implementacja (tłumaczenie na C):

int WspNewtona(unsigned int n, unsigned int k)
{
    unsigned wynik = 1;
    for(unsigned int i=1;i<=k;++i)
        wynik = wynik * (n - i + 1) / i;

    return wynik;
}
0

Co do alokacji pamięci zdecydowanie skorzystaj z tego co MarekR22 zaproponował.

1 użytkowników online, w tym zalogowanych: 0, gości: 1