Kirjoittaja Aihe: Todella kummallinen ongelma.  (Luettu 5899 kertaa)

Pörzi

  • Käyttäjä
  • Viestejä: 99
    • Profiili
    • http://fugufish.dy.fi/
Todella kummallinen ongelma.
« : 24.06.07 - klo:18.24 »
Tämä koodi (siis on siinä tottakai muutakin):
Koodia: [Valitse]
int pituus=3;
float pallo[pituus][3];
Kääntyy ihan oikein, mutta kun sen ajaa, tulee: Segmentation fault (core dumped), joka kai tarkoittaa sitä, että taulukon ulkopuolelta yritettiin lukea/kirjoittaa. (Tämä tapahtuu myöhemmin koodissa, mutta sillä ei ole mitään väliä, koska) Segmentation faulttia ei tule, jos laitan:
Koodia: [Valitse]
int pituus=3;
float pallo[3][3];

Näiden maalaisjärjen mukaisesti pitäisi molempien tehdä ihan samanlainen taulukko. Missä vika? Avusta olisin todella kiitollinen.

janne

  • Käyttäjä
  • Viestejä: 5150
    • Profiili
Vs: Todella kummallinen ongelma.
« Vastaus #1 : 24.06.07 - klo:19.37 »
Tämä koodi (siis on siinä tottakai muutakin):
Koodia: [Valitse]
int pituus=3;
float pallo[pituus][3];

ihan tarkaalleen ottaen tämä ei ole kielen määritysten mukaan (oletan siis, että kieli on c tai c++) sallittua, vaan taulukon koko pitää olla tiedossa käännösaikana. kääntäjä saattaa kyllä hanskata tuollaisenkin esittelyn jos tuota pituus muuttujaa ei tuossa välissä muuteta.

Kääntyy ihan oikein,

paitsi -pedantic -vivulla.

mutta kun sen ajaa, tulee: Segmentation fault (core dumped), joka kai tarkoittaa sitä, että taulukon ulkopuolelta yritettiin lukea/kirjoittaa.

sehän selviäisi helposti jos ajaisi koodia debuggerissa ;)

Näiden maalaisjärjen mukaisesti pitäisi molempien tehdä ihan samanlainen taulukko. Missä vika? Avusta olisin todella kiitollinen.

oletko kokeillut tulostaa luodun taulukon kokoa luomisen jälkeen (tai tarkistaa sitä debuggerissa)?
Janne

Pörzi

  • Käyttäjä
  • Viestejä: 99
    • Profiili
    • http://fugufish.dy.fi/
Vs: Todella kummallinen ongelma.
« Vastaus #2 : 24.06.07 - klo:19.43 »
Tämä koodi (siis on siinä tottakai muutakin):
Koodia: [Valitse]
int pituus=3;
float pallo[pituus][3];

ihan tarkaalleen ottaen tämä ei ole kielen määritysten mukaan (oletan siis, että kieli on c tai c++) sallittua, vaan taulukon koko pitää olla tiedossa käännösaikana. kääntäjä saattaa kyllä hanskata tuollaisenkin esittelyn jos tuota pituus muuttujaa ei tuossa välissä muuteta.

Kääntyy ihan oikein,

paitsi -pedantic -vivulla.

mutta kun sen ajaa, tulee: Segmentation fault (core dumped), joka kai tarkoittaa sitä, että taulukon ulkopuolelta yritettiin lukea/kirjoittaa.

sehän selviäisi helposti jos ajaisi koodia debuggerissa ;)

Näiden maalaisjärjen mukaisesti pitäisi molempien tehdä ihan samanlainen taulukko. Missä vika? Avusta olisin todella kiitollinen.

oletko kokeillut tulostaa luodun taulukon kokoa luomisen jälkeen (tai tarkistaa sitä debuggerissa)?
Ööh, mites sen debuggauksen saa tehtyä shelissä?  :-[ (tai essolla. :D)

Juu eli tämä on ensimmäinen kunnon projektini C++ ja SDL:llä, joten yrittäkää olla kärsivällisiä. Tiedän kyllä, että parin kuukauden päästä tämä tekemäni koodi tuntuu itsestänikin jo ihan kamalalta, mutta tekemällä oppii...

janne

  • Käyttäjä
  • Viestejä: 5150
    • Profiili
Vs: Todella kummallinen ongelma.
« Vastaus #3 : 24.06.07 - klo:22.02 »
Ööh, mites sen debuggauksen saa tehtyä shelissä?  :-[ (tai essolla. :D)

no siis debuggaamiseen ilmeisin työkalu linuxissa on varmaan gdb, tosin jos et ole sitä koskaan käyttänyt, niin siihen joutuu ensin hieman perehtymään. dokumentaatio on kuitenkin aika hyvää ja taidosta on varmasti hyötyä myöhemminkin.

Juu eli tämä on ensimmäinen kunnon projektini C++ ja SDL:llä, joten yrittäkää olla kärsivällisiä. Tiedän kyllä, että parin kuukauden päästä tämä tekemäni koodi tuntuu itsestänikin jo ihan kamalalta, mutta tekemällä oppii...

juu, koodaamaan oppii vain koodaamalla.
Janne

mgronber

  • Käyttäjä
  • Viestejä: 1458
    • Profiili
Vs: Todella kummallinen ongelma.
« Vastaus #4 : 24.06.07 - klo:23.08 »
Juu eli tämä on ensimmäinen kunnon projektini C++ ja SDL:llä, joten yrittäkää olla kärsivällisiä. Tiedän kyllä, että parin kuukauden päästä tämä tekemäni koodi tuntuu itsestänikin jo ihan kamalalta, mutta tekemällä oppii...
juu, koodaamaan oppii vain koodaamalla.

...ja lukemalla muiden kirjoittamaa koodia.

Pörzi

  • Käyttäjä
  • Viestejä: 99
    • Profiili
    • http://fugufish.dy.fi/
Vs: Todella kummallinen ongelma.
« Vastaus #5 : 26.06.07 - klo:16.12 »
Kiersin tuon ongelman kirjoittamalla käsin 3 siihen taulukkoon ja jatkoin ohjelmointia... Nyt taas kävin ongelman kimppuun. Ilmeisesti muussa koodissa tehtyjen muutosten vuoksi ohjelma toimiikin ihan oikein tuota muuttujaa käytettäessä. Kuitenkin jos kokeilen laittaa siihen arvoksi 100, tulee pelkästään musta ruutu. Jos luku on 80, toimii ihan oikein. Kokeilin sitten debugata, mutta siitä ei tunnu olevan mitään hyötyä:
Starting program: /home/a/Desktop/a.out
[Thread debugging using libthread_db enabled]
[New Thread -1213995312 (LWP 6548)]

Program terminated with signal SIGKILL, Killed.
The program no longer exists.

Ja tuo SIGKILL -signaali oli minun tekemäni... ohjelma ei vastannut millään tavalla, eikä myöskään suostunut sulkeutumaan. (ilman killiä) joitain muita ongelmia onnistuin kyllä tuolla debuggerilla löytämään, mutta nyt se ei tunnu antavan oikein mitään tietoa... (enkä osaa edistyneempiä systeemejä tuosta debuggerista käyttää :(, vaikka hyvä manuska onkin )

Edit: ja niin siis:
int pituus=100;
float pallo[pituus][3];
-->
musta ruutu

int pituus=100;
float pallo[100][3];
-->
toimii
« Viimeksi muokattu: 26.06.07 - klo:16.18 kirjoittanut Pörzi »

janne

  • Käyttäjä
  • Viestejä: 5150
    • Profiili
Vs: Todella kummallinen ongelma.
« Vastaus #6 : 26.06.07 - klo:18.44 »
Edit: ja niin siis:
int pituus=100;
float pallo[pituus][3];
-->
musta ruutu

int pituus=100;
float pallo[100][3];
-->
toimii

koska minä olen tietyllä tapaa pilkunviilaaja, koitan nyt sitten lähestyä tätä ongelmaa toiselta kantilta...
miksi sinä haluat määritellä tuon taulukon koon muuttujan avulla? tai mitä hyötyä siitä on sinulla? tuon lyhyen snipletin perusteella ei mitään, mutta minä en tiedäkään mitä siinä välissä tapahtuu.

tuota pituus-muuttujaa ei kuitenkaan saa muuttaa ennen tuon taulukon määrittelemistä sillä, kuten jos aiemmin sanoin, taulukon koon pitää olla tiedossa käännösaikana. vapaasti skaalautuvat taulukot luodaan sitten dynaamisesti ajon aikana tai käytetään jotain itsessään dynaamista tietorakennetta homman hoitamiseen. sikäli kun kyseessä on vain magic numbereista eroon pääseminen, niin se pitäisi hoitaa sitten definellä tai (static?) const-tyyppisellä muuttujalla.
Janne

Pörzi

  • Käyttäjä
  • Viestejä: 99
    • Profiili
    • http://fugufish.dy.fi/
Vs: Todella kummallinen ongelma.
« Vastaus #7 : 26.06.07 - klo:22.13 »
koska minä olen tietyllä tapaa pilkunviilaaja, koitan nyt sitten lähestyä tätä ongelmaa toiselta kantilta...
miksi sinä haluat määritellä tuon taulukon koon muuttujan avulla? tai mitä hyötyä siitä on sinulla? tuon lyhyen snipletin perusteella ei mitään, mutta minä en tiedäkään mitä siinä välissä tapahtuu.

tuota pituus-muuttujaa ei kuitenkaan saa muuttaa ennen tuon taulukon määrittelemistä sillä, kuten jos aiemmin sanoin, taulukon koon pitää olla tiedossa käännösaikana. vapaasti skaalautuvat taulukot luodaan sitten dynaamisesti ajon aikana tai käytetään jotain itsessään dynaamista tietorakennetta homman hoitamiseen. sikäli kun kyseessä on vain magic numbereista eroon pääseminen, niin se pitäisi hoitaa sitten definellä tai (static?) const-tyyppisellä muuttujalla.
Juu siis hyöty jää varsin vähäiseksi... lähinnä vaan kiinnostaa, miksi näin tapahtuu. Yleensä ohjelmoinnissa olen nähnyt hyväksi yrittää ymmärtää ongelmaa sen kiertämisen lisäksi.

Määrittelin tuon muuttujan const intiksi ja kappas kummaa homma toimii taas... vaikkei sitä missään vaiheessa yritettykään muuttaa. (kääntäjähän herjaisi siinä vaiheessa, kun constiin yritetään sijoittaa). Eniten minua tässä hämää se, että tämä toimii vallan mainiosti ilman constia toisessa kohtaa koodissani, jossa oikeasti tarvitsen sitä. (luetaan tekstitiedoston alusta numero, joka määrittää taulukon koon...)

Kiitos! Tuo toinen näkökulmasi sai minut miettimään constia... edelleen kyllä mietityttää, mistä oikein on kyse, mutta tämä toimii, joten olen tyytyväinen. Rupean tosissani ratkomaan tätä "ongelmaa" siinä vaiheessa, kun tulee tekemisen puutetta.

janne

  • Käyttäjä
  • Viestejä: 5150
    • Profiili
Vs: Todella kummallinen ongelma.
« Vastaus #8 : 27.06.07 - klo:00.19 »
Juu siis hyöty jää varsin vähäiseksi... lähinnä vaan kiinnostaa, miksi näin tapahtuu. Yleensä ohjelmoinnissa olen nähnyt hyväksi yrittää ymmärtää ongelmaa sen kiertämisen lisäksi.

tämä on kyllä varmasti ihan hyvä lähestymistapa ongelmiin, mutta tosiaan minun nähdäkseni ongelma oli siinä, että sinun koodisi oli kirjoitettu kielen speksien vastaisesti. tämä tarkoittaa käytännössä, että jos kääntäjä päästää koodin joillain löyhillä asetuksilla läpi, se saattaa toimia. voi myös olla, että se ei toimi ja sinulla se ei toiminut.

Määrittelin tuon muuttujan const intiksi ja kappas kummaa homma toimii taas... vaikkei sitä missään vaiheessa yritettykään muuttaa.

kääntäjä ei välttämättä pysty (tai viitsi) tarkistamaan muutetaanko jotain muuttujaa suoraan tai välillisesti jossain vaiheessa. siis muuttaminenhan voi tapahtua vaikka pelkän muistiosoitteen kautta toisessa säikeessä sattumanvaraiseen aikaan.

(kääntäjähän herjaisi siinä vaiheessa, kun constiin yritetään sijoittaa).

totta kyllä.

Eniten minua tässä hämää se, että tämä toimii vallan mainiosti ilman constia toisessa kohtaa koodissani, jossa oikeasti tarvitsen sitä. (luetaan tekstitiedoston alusta numero, joka määrittää taulukon koon...)

jos taulukko varataan tuossa toisessakin kohtaa staattisesti, niin homma voi räjähtää käsiin milloin tahansa. jos taas muisti varataan taulukolle dynaamisesti,niin mitään ongelmaa ei pitäisi olla.

Tuo toinen näkökulmasi sai minut miettimään constia... edelleen kyllä mietityttää, mistä oikein on kyse, mutta tämä toimii, joten olen tyytyväinen. Rupean tosissani ratkomaan tätä "ongelmaa" siinä vaiheessa, kun tulee tekemisen puutetta.

voi hyvin olla, että joudut ongelmaa ratkoessasi perehtymään kääntäjän sielunelämään. tällaistenkin tapausten vuoksi on ihan hyvä käyttää kääntäjän vipuja jotka esim. käsittelevät kaikkia varoituksia virheinä ja vaikka sitä jo mainittua pedanticia. näin koodista tulee varmasti speksien mukaista ja sen voi olettaa toimivan suht samalla tavalla eri kääntäjillä (tai jopa samalla kääntäjällä eri ympäristössä). tällaisissa tapauksissa siitä ei ole mitään takeita.
Janne

mgronber

  • Käyttäjä
  • Viestejä: 1458
    • Profiili
Vs: Todella kummallinen ongelma.
« Vastaus #9 : 27.06.07 - klo:00.57 »
Eniten minua tässä hämää se, että tämä toimii vallan mainiosti ilman constia toisessa kohtaa koodissani, jossa oikeasti tarvitsen sitä. (luetaan tekstitiedoston alusta numero, joka määrittää taulukon koon...)

Sinun pitää varata muisti dynaamisesti malloc()-kutsun avulla ja lopuksi se tulee vapauttaa free()-kutsulla.

Varaamattomaan muistiin kirjoittamisen seuraukset riippuvat aina auringonpilkkujen määrästä ja Merkuriuksen suhteesta Uranukseen ja Epsilon Indiin. Koodi saattaa ensimmäisellä kerralla toimia mutta yhden muuttujan lisäämisen jälkeen toiminta saattaa lakata. Tässä tapauksessa myös erikokoiset tiedostot voivat aiheuttaa ohjelman kaatumisen.

Suosittelen että ajat koodisi valgrindin alla käyttäen memcheck-työkalua jolloin saat tuollaiset muistivirheet kiinni.

peran

  • Vieras
Vs: Todella kummallinen ongelma.
« Vastaus #10 : 27.06.07 - klo:01.38 »
Osoitinten kanssa kannattaa olla varovainen, sillä niillä saa todella monimutkaisia tietorakenteita kasattua.

Tai verkko-han on tietenkin monimutkaisin tietorakenne, minkä osoittimilla saa aikaiseksi, mutta kun poistaa yhden solmun verkosta, eikä tiedä mitkä kaikki solmut osoittaa ko. solmuun onkin jo soppa valmis. (Verkkoa monimutkaisempaa tietorakennetta ei käsittääkseni ole - vai tunteeko joku sellaisen?)

<OffTopic>
Hiljattain tuli tein itselleni liian monimutkaisen tietorakenteen. Kuten yleensäkin - myös siinä tietorakenteessa tehtyjen virheiden korjaamiseksi on helpompaa tehdä uusi ohjelma kuin korjata pelkästään rakenne. Kun on enemmän ohjelmoinut Javaa ja .NETtiä, niin unohtuu tietorakenteen korjaamisen tärkeys - vaikka kyllä niihinkin voi saada aikaiseksi muistivuotoja - ainakin käsittääkseni, vaikken olekaan demonnut 'toimiiko' ideani siinä suhteessa.
</OffTopic>

mk1970

  • Käyttäjä
  • Viestejä: 213
    • Profiili
Vs: Todella kummallinen ongelma.
« Vastaus #11 : 27.06.07 - klo:07.45 »
no siis debuggaamiseen ilmeisin työkalu linuxissa on varmaan gdb

Jotta alkushokki olisi hieman pienempi niin kokeile DDD:llä debuggausta.

Koodia: [Valitse]
# sudo aptitude install ddd
# ddd ohjelma

Sitten komennat run (tai run --oma --toinen eli kaikki mahdolliset argumentit omalle ohjelmallesi tuon run-komennon jälkeen). Lisäile breakpointteja koodiisi, hypi step ja/tai next -komennoilla, jne.

Pörzi

  • Käyttäjä
  • Viestejä: 99
    • Profiili
    • http://fugufish.dy.fi/
Vs: Todella kummallinen ongelma.
« Vastaus #12 : 27.06.07 - klo:13.43 »
Ok... Kiitoksia taas kaikille! Tänään kun rupesin taas ohjelmoimaan eteenpäin, huomasin, etten ollutkaan onnistunut korjaamaan ongelmaa...
Lainaus
Varaamattomaan muistiin kirjoittamisen seuraukset riippuvat aina auringonpilkkujen määrästä ja Merkuriuksen suhteesta Uranukseen ja Epsilon Indiin. Koodi saattaa ensimmäisellä kerralla toimia mutta yhden muuttujan lisäämisen jälkeen toiminta saattaa lakata. Tässä tapauksessa myös erikokoiset tiedostot voivat aiheuttaa ohjelman kaatumisen.
Tämä on vaan niin totta! :D

Koodista pitäisi vielä tehdä jossain vaiheessa windows-käännös, joten pitää koittaa tehdä tarkemmin, että toimii muillakin kääntäjillä. Takaisin sorvin ääreen...

janne

  • Käyttäjä
  • Viestejä: 5150
    • Profiili
Vs: Todella kummallinen ongelma.
« Vastaus #13 : 27.06.07 - klo:23.42 »
Sinun pitää varata muisti dynaamisesti malloc()-kutsun avulla ja lopuksi se tulee vapauttaa free()-kutsulla.

no, ihan tarkalleen ottaen c++ -ohjelmassa on varmaan syytä käyttää new ja delete kutsuja, vaikka c:stä peräisin olevatkin toimisivat. niiden ristiin käyttäminen ei ole suotavaa. tietty vaihtoehtona voi olla jonkun käytetyn toolkitin vastaavat funktiot, joita ehkä pitääkin käyttää jos haluaa käyttää kirjaston tarjoamia tietorakenteita ja niiden automaattista musitin vapauttamista.

Suosittelen että ajat koodisi valgrindin alla käyttäen memcheck-työkalua jolloin saat tuollaiset muistivirheet kiinni.

kyl.
Janne

mgronber

  • Käyttäjä
  • Viestejä: 1458
    • Profiili
Vs: Todella kummallinen ongelma.
« Vastaus #14 : 28.06.07 - klo:00.44 »
Sinun pitää varata muisti dynaamisesti malloc()-kutsun avulla ja lopuksi se tulee vapauttaa free()-kutsulla.

no, ihan tarkalleen ottaen c++ -ohjelmassa on varmaan syytä käyttää new ja delete kutsuja, vaikka c:stä peräisin olevatkin toimisivat.

Aivan totta. Minulta jäikin huomaamatta että tuossa yhdessä viestissä kerrottiin ohjelmointikielen olevan C++. Katsoin vain aloitusviestin ja sen perusteella tein oletuksen että kielenä olisi ollut C.