Stack Overflow -virheiden välttäminen
Rajaa rekursio hallittavaksi.
Stack Overflow -virheiden välttäminen on ilmainen C Academy-oppitunti CoddyKitissä. Tämä on oppitunti 4/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu C Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. C Academy-kurssilla on yhteensä 4 oppituntia.
Mikä on pinon ylivuoto
Kutsupinon koko on rajallinen. Jokainen funktiokutsu käyttää osan siitä parametreihin ja paikallisiin muuttujiin.
Jos rekursio menee liian syvälle, pino täyttyy ja ohjelma kaatuu pinon ylivuotoon.
Puuttuva perustapaus
Yleisin syy on perustapaus, jota ei koskaan saavuteta. Tämä jatkuu loputtomasti ja aiheuttaa pinon ylivuodon.
Älkää suorittako tällaista funktiota, vaan tutkikaa, miksi se epäonnistuu.
int broken(int n) {
/* no base case: never stops */
return broken(n + 1);
}Argumentti ei pienene
Pelkkä perustapaus ei riitä, vaan argumentin on edettävä sitä kohti. Tässä n kasvaa, joten se ei koskaan saavuta arvoa 0.
Tarkistakaa aina, että jokainen kutsu pääsee lähemmäksi lopetusehtoa.
int oops(int n) {
if (n == 0) return 0;
return oops(n + 1); /* wrong direction */
}Oikea versio
Kun suunta korjataan, suoritus päättyy. Nyt n pienenee kohti perustapausta 0.
#include <stdio.h>
int good(int n) {
if (n == 0) return 0;
return n + good(n - 1);
}
int main(void) {
printf("%d\n", good(10));
return 0;
}Syvyysrajat ovat todellisia
Oikeakin rekursio voi aiheuttaa pinon ylivuodon, jos se on hyvin syvää. Funktion kutsuminen miljoonien tasojen syvyyteen voi ylittää pinon koon, joka on usein vain muutamia megatavuja.
Jos syvyys on erittäin suuri, suosikaa iteraatiota.
Muunna syvä rekursio silmukaksi
Jos rekursion syvyys kasvaa syötteen koon mukana, vaihtakaa silmukkaan. Näin vältätte tuhansien kehysten kertymisen pinoon.
Alla oleva silmukka summaa luvut 1:stä suureen n:ään turvallisesti vakiomäärällä muistia.
#include <stdio.h>
int main(void) {
long total = 0;
for (int i = 1; i <= 1000000; i++)
total += i;
printf("%ld\n", total);
return 0;
}Pienennä syvyyttä hajota ja hallitse -menetelmällä
Työn jakaminen puoliksi pitää syvyyden pienenä. Alueen summaaminen puolittamalla kasvattaa syvyyttä koon logaritmin tavoin lineaarisen kasvun sijaan.
long range_sum(int lo, int hi) {
if (lo == hi) return lo;
int mid = (lo + hi) / 2;
return range_sum(lo, mid) + range_sum(mid + 1, hi);
}Varo suuria paikallisia taulukoita
Suuret paikalliset muuttujat tekevät jokaisesta kehyksestä raskaan, joten pino täyttyy nopeammin.
Välttäkää suurten taulukoiden määrittelyä rekursiivisen funktion sisällä. Välittäkää sen sijaan osoittimia tai käyttäkää kekoa.
void heavy(int n) {
int buffer[10000]; /* big frame each call */
if (n == 0) return;
heavy(n - 1);
}Käytä kertymämuuttujaa
Juoksevan summan välittäminen kertymämuuttujana pitää jokaisen kehyksen pienenä ja tekee rekursiosta häntärekursion kaltaisen.
Tällöin jotkin kääntäjät voivat käyttää yhtä kehystä uudelleen.
#include <stdio.h>
long sum_acc(int n, long acc) {
if (n == 0) return acc;
return sum_acc(n - 1, acc + n);
}
int main(void) {
printf("%ld\n", sum_acc(100, 0));
return 0;
}Turvallisuustarkistuslista
Ennen kuin luotatte rekursiiviseen funktioon, tarkistakaa:
1. Onko siinä perustapaus?
2. Eteneekö jokainen kutsu sitä kohti?
3. Voiko syvyys kasvaa erittäin suureksi suurella syötteellä?
Jos syvyys voi kasvaa hallitsemattomasti, käyttäkää silmukkaa.
Testaa pienillä syötteillä
Testatkaa rekursiota aina ensin pienillä syötteillä, joiden tuloksen voitte tarkistaa käsin.
Jos pienet tapaukset toimivat ja syvyys pysyy rajattuna, voitte kasvattaa kokoa luottavaisin mielin.
Pikatarkistus
Tunnista turvallisin korjaus.
Kertaus
Pinon ylivuoto tapahtuu, kun rekursio menee liian syvälle tai ei lopu koskaan. Määritelkää aina saavutettava perustapaus, pienentäkää argumenttia jokaisella kutsulla, pitäkää kehykset kevyinä ja vaihtakaa iteraatioon, kun syvyys voi kasvaa syötteen koon mukana.
Opi C tekoälytuutorin avulla — ilmaiseksi
Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.
- Kurssit
- 39
- Oppitunnit
- 144
Usein kysytyt kysymykset
Onko oppitunti ”Stack Overflow -virheiden välttäminen” ilmainen?
Kyllä – oppitunnin ”Stack Overflow -virheiden välttäminen” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko C Academy-kurssin, päivitä CoddyKit PROhon. C Academy-kurssilla on yhteensä 4 oppituntia.
Mitä opin oppitunnilla ”Stack Overflow -virheiden välttäminen”?
Rajaa rekursio hallittavaksi. Harjoittelet C Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.
Tarvitsenko kokemusta aloittaakseni C Academy-opiskelun?
Aiempi kokemus ei ole tarpeen. CoddyKitin C Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 4/4.
Kuinka kauan ”Stack Overflow -virheiden välttäminen”-oppitunnin suorittaminen kestää?
Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.
Voinko kirjoittaa ja suorittaa koodia tällä C Academy-oppitunnilla?
Kyllä. Jokainen C Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.
Kaikki tämän kurssin oppitunnit
- Miten rekursio toimii
- Klassiset rekursio-ongelmat
- Rekursio verrattuna iteraatioon
- Stack Overflow -virheiden välttäminen