Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++: Ongelma: Muuttuja muuttuu vaikken sitä muuta!

Sivun loppuun

verho88 [20.10.2010 18:31:34]

#

Moi.

Olen nyt toista viikkoa taas paininut erään ongelman kanssa ja en millään saa kyseistä virhettä selville. Asensin kubuntunkin, jotta pääsen valgrindillä etsimään mahdollista virheen aiheuttajaa mutta turhaan. Joko en ymmärrä mitä se sanoo tai ymmärrän mutta valgrind ei löydä ongelmaa. Siispä nyt ajattelin kysyä täällä jospa joku löytäisi virheen tai jonkin suunnitteluvirheen tai muun koodista joka aiheuttais virheen.

Eli siis syvemmälle ongelmaan: Teinpäs tuollaisen systeemin, joka lataa 3D-mallin ja sille skeletonin. Ymmärtääkseni kaikki sujuu latauksissa hyvin, mutta kun alan kiertämään ja laskemaan skeletonia yhtäkkiä luiden Rot-muuttuja muuttuu, vaikkei siihen missään kirjoteta mitään, luetaan vain ja kierretään luuta tai ulottuvuutta niiden mukaan.

Valgrind sanoo, että "Conditional jump or move depends on uninitialised value(s)", mutta ymmärtääkseni kyseinen bone :: Rot-muuttuja alustetaan kun luu eli bone luodaan, sillä Rot on vec3-luokan muuttuja joka aina luodessa alustetaan nolliksi. Tuokin virhe hävisi kun mat4:: RotX funktiota muutin ottamaan vastaan const float angle-arvon float anglen sijasta...

Eli vielä: ennen kun kutsun luulle Rotate()-funktiota luiden Rot on 0.0 0.0 0.0, mutta kun Rotate()-funktio on kutsuttu lapsien Rot muuttuu 1.0 0.0 0.0ksi. Jostakin joku kirjoittaa jotain väärään muistipaikkaan mutta en löydä mistään sitä mikä sen tekee?

Koodia:

main.cpp

#include <iostream>
#include <cstdio>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ctime>

#include <GL/gl.h>

using namespace std;

#include "esittelyt.hpp"
#include "vektorit.hpp"
#include "tietueet.hpp"

int main(void)
{
    bone *root=0;
    model malli;
    mat4 dim;
    vec3 Rot;
    bone *u=0;


    root = new bone;

    if( root->LoadSkeleton("skeleton.m3d") == 0 ) { delete root; return 1; }
    else printf("Ladattiin skeleton.\n");
    if( malli.LoadMesh("skeleton.m3d") == 0 ) { delete root; return 1; }
    else printf("Ladattiin malli.\n");
    if( malli.AttachBonesToVertexes("skeleton.m3d", root) == 0) { delete root; return 1; }
    else printf("Yhdistettiin luuranko malliin.\n");

    u = boneFindByID(root, 1);
    if(u) Rot = u->GiveRotation();
    printf("Rotation: %f %f %f\n", Rot.x, Rot.y, Rot.z);

    root->Rotate();
    printf("Kierrettiin luurankoa!\n");


    // mahdolliset sekoilun aiheuttajat:
    // Rotate();
    // GiveDimension();
    // Rotate(mat4 a);
    // GiveDimension2();
    // mat4:n kertolasku

    // GiveDimension():ssa
    // matriisien kiertomuodostajat mat4 :: Rot.x Rot.y Rot.z

    // LoadSkeleton-funktio
    // AddChild-funktio
    // bonen kopiointifunkkari
    // SetName()
    // SetID()
    // SetDimension()

    //malli.CalcVertexes(true);
    //printf("Laskettiin verteksien paikat.");
    if(root) delete root;

    return 0;
}

tietueet.hpp (karsittu epäolennaisuuksia pois)

bone :: bone()
{
	ID = 0;
	Children = 0;
	Child = 0;
	Scale = vec3(1.0, 1.0, 1.0);
	name = "";
}

bone :: bone(unsigned int a, mat4 b)
{
	ID = a;
	dimension = b;
	Children = 0;
	Child = 0;
	Scale = vec3(1.0, 1.0, 1.0);
	name = "";
}

bone :: ~bone()
{
	Free(); // tyhjennä
}

void bone :: Free()
{
    unsigned int i;
    for(i=0; i<Children; i++)
    {
        // ensin käydään kaikki lapset läpi ja tyhjennetään niiden muistit
        Child[i].Free();
    }
    // lopuksi tyhjennetään omat
    ID = 0;
    if(Child != 0) { delete [] Child; Child=0; }
    //if(name != 0) { delete [] name; name = 0; }
    Children = 0;
    name = "";
}

bool bone :: AddChild(unsigned int bID, const char* bName, mat4 bDim )
{
    // lisää luulle lapsen
    // ehkä jonkilainen lista tai vektori systeemi olis kätevämpi?
    bone *temp=0;
	unsigned int i;

	if(Children > 0) // jos oli lapsia
	{
		temp = new bone[Children]; // tehdään taulukko jonne mahtuu kaikki lapset

		if(temp == 0)
		{
            fprintf(stderr, "Muistin varaaminen epäonnistui!\n");
            return false;
        }

		for(i=0; i<Children; i++) // käydään lapset yksitellen läpi ja kopioidaan ne
		{
			if(!(temp[i] = Child[i]))
			{
			    fprintf(stderr, "Virhe luiden kopioinnissa!\n");
                if(temp != 0) { delete [] temp; temp = 0; } // jos temp luotiin
                return false;
			}
		}
	}

    if(Child != 0) { delete [] Child; Child=0; } // poistetaan edellinen taulukko
	Child = new bone[Children+1]; // luodaan uus taulukko johon mahtuu myös uus lapsi

	if(Child == 0)
	{
        fprintf(stderr, "Muistin varaaminen epäonnistui!\n");
        if(temp != 0) { delete [] temp; temp = 0; } // jos temp luotiin
        return false;
    }

	for(i=0; i<Children; i++) // käydään lapset yksitellen läpi ja kopioidaan ne
	{
		if( !(Child[i] = temp[i]) )
		{
            fprintf(stderr, "Virhe luiden kopioinnissa!\n");
            if(temp != 0) { delete [] temp; temp = 0; } // jos temp luotiin
            return false;
        }
	}
	if(temp != 0) { delete [] temp; temp = 0; } // jos temp luotiin

	Child[Children].SetID( bID );
	Child[Children].SetName( bName );
	Child[Children].SetDimension( bDim );

    Children++; // kasvatetaan lapsien määrää
    return true; // onnistunut suoritus
}


void bone :: SetDimension( mat4 a ) // aseta alkup. ulottuvuus
{
	dimension = a;
}
void bone :: SetID( unsigned int a ) // aseta ID, tunniste
{
	ID = a;
}
void bone :: SetName( const char *nimi ) // aseta luun nimi
{
    name = nimi;
}
unsigned int bone :: GiveID() // anna ID
{
	return ID;
}
const char* bone :: GiveName() // anna nimi
{
    return name.c_str();
}

mat4 bone :: CalcDimension() // laskee tämän hetkisen absoluuttisen ulottuvuuden
{
	// globaalien akseleiden mukaan
	mat4 a, b;

	// nyt x z y
	a.RotX(Rot.x); b*=a; // muutetaan myöhemmin qvaternioilla laskemiseksi
	a.RotZ(Rot.z); b*=a;
	a.RotY(Rot.y); b*=a;

	b.arvo[0] *= Scale.x;
	b.arvo[1] *= Scale.x;
	b.arvo[2] *= Scale.x;

	b.arvo[4] *= Scale.y;
	b.arvo[5] *= Scale.y;
	b.arvo[6] *= Scale.y;

	b.arvo[8] *= Scale.z;
	b.arvo[9] *= Scale.z;
	b.arvo[10] *= Scale.z;

	b.arvo[12] = Pos.x;
	b.arvo[13] = Pos.y;
	b.arvo[14] = Pos.z;

	return dimension*b; // elikkä alkup.dimensio*b on uusi ulottuvuus dimension*b
}

mat4 bone :: GiveDimension() // palauttaa tämän hetkisen absoluuttisen ulottuvuuden
{
	return dimension_new;
}

mat4 bone :: getDimension()
{
	return dimension;
}

vec3 bone :: GiveRotation()
{
    return Rot;
}

bone* bone :: FindByID(unsigned int f_ID)
{
	unsigned int i;
	bone* u=0;
	for(i=0; i<Children; i++)
	{
		if(Child[i].GiveID() == f_ID) return &Child[i];
		u = Child[i].FindByID(f_ID);
		if(u != 0) return u;
	}
	return 0;
}

bone* bone :: FindByName( const char* nimi )
{
    unsigned int i;
    bone* u=0;
    for(i=0; i<Children; i++)
    {
        if( strcmp( Child[i].GiveName() ,nimi) == 0 ) return &Child[i];
        u = Child[i].FindByName( nimi );
        if(u != 0) return u;
    }
    return 0;
}

void bone :: Rotate()
{
    // tämä laskee dimension_new:iin uuden ulottuvuuden
    // ja kiertää sitten sen mukaan lapsia
	unsigned int i;
	//if(ID != 0) dimension2 = dimension; // locaalit
	dimension_new = CalcDimension(); // globaalien pyörimisakseleiden mukaan laskettu ulottuvuus
	for(i=0; i<Children; i++)
	{
		//if( ID == 0) Child[i].Rotate( dimension ); // locaalit
		//else Child[i].Rotate( dimension2 ); // locaalit
		Child[i].Rotate( dimension_new ); // kierrä sen mukaan lapsia (globaalit kiertoakselit)
	}
}

void bone :: Rotate( mat4 a )
{
    // annetulla matriisilla kierretään ja translatoidaan ja skaalataan tätä bonea
	unsigned int i;
	mat4 b, c;

	//if(ID != 0) dimension2 = a*dimension; // locaalit

	b = CalcDimension();

	c = a * b; // matriisien kertolasku sekoilee täh?!?

	dimension_new = c;

	// eli mun ulottuvuus on parentin ulottuvuus * oma relatiivinen ulottuvuus...
    // ...(jossa skaalaus rotaatio ja translaatio) parenttiin

	for(i=0; i<Children; i++)
	{
        // lapsia sen jälkeen kierretään taas oman ulottuvuuden mukaan

		//if(ID == 0)	Child[i].Rotate( dimension ); // locaalit
		//else Child[i].Rotate( dimension2 ); // locaalit
		Child[i].Rotate( dimension_new ); // globaalit
	}
}

int bone :: LoadSkeleton(const char *fileName) // lataa tiedostosta skeletonin
{
	FILE *tiedosto=0;
	unsigned int i=0;
	unsigned int f_ID = 0;
	unsigned int f_childof=0;
	char buffer[512];
	string nimi;
	char joku[512];
	float f[16];
	vec4 a, b, c, d;

	//bone temp;

	tiedosto = fopen(fileName, "r");
	if(tiedosto == NULL)
    {
        //fclose(tiedosto); // ei kai sitä tarvitse sulkea jos se ei edes auennu?
        fprintf(stderr, "Tiedoston avaaminen ei onnistu: %s\n", fileName);
        return 0;
    }

	while(!feof(tiedosto))
	{
		strcpy(buffer, "");
		fgets(buffer, 512, tiedosto);

		if( sscanf(buffer, "b %u %u %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %s\n", &f_ID, &f_childof, &f[0], &f[1], &f[2], &f[3], &f[4], &f[5], &f[6], &f[7], &f[8], &f[9], &f[10], &f[11], &f[12], &f[13], &f[14], &f[15], &joku) == 19 )
		{
			a = vec4(f[0], f[1], f[2], f[3]); // pystyvektoreita!
			b = vec4(f[4], f[5], f[6], f[7]);
			c = vec4(f[8], f[9], f[10], f[11]);
			d = vec4(f[12], f[13], f[14], f[15]);

			nimi = joku;

			if(ID == 0 && f_ID == ID)
			{
				dimension = mat4(a, b, c, d); // ulottuvuus rootille
				SetName( nimi.c_str() );
			}
			else if(f_childof == ID)
			{
				//temp.SetDimension( mat4(a, b, c, d) );
				//temp.SetID( f_ID );
                //temp.SetName( nimi.c_str() );
				//if(!AddChild( temp ) ) return 0;
				if( !AddChild( f_ID, nimi.c_str(), mat4(a, b, c, d) ) ) return 0;
			}
		}
	}
	fclose(tiedosto);

	for(i=0; i<Children; i++)
	{
		if( Child[i].LoadSkeleton(fileName) == 0)
        {
            fprintf(stderr, "Luurangon lataaminen epäonnistui! Tiedosto: %s\n", fileName);
            return 0;
        }
	}

	return 1; // onnistunut
}

bool bone :: operator = (bone a) // kopioidaan pari muuttujaa luusta toiseen
{
	ID = a.GiveID(); // kopioi ID
	Children = 0; // lapsia ei kopioida koska niitä ei tätä funktiota kutsuessa vielä ole!
	if(Child != 0) { delete [] Child; Child = 0; } // varmistetaan
	dimension = a.getDimension(); // ulottuvuudet kopataan

	//dimension_new = a.GiveDimension2(); // ei välttistä tartte koska tätä kopiointia käytetään vaan kun malli ladataan!
    name = a.GiveName();
    return true;
}

void bone :: TellMe() // kertoo luusta ja sen lapsista eri asioita
{
	unsigned int i;
	mat4 temp_mat;
	//fprintf(stdout, "ID: %i Name: %s Children: %i\n", ID, name, Children);
	fprintf(stdout, "ID: %i Name: %s Children: %i\n", ID, name.c_str(), Children);
	//printf("Rot: %f %f %f\n", Rot.x, Rot.y, Rot.z);

	for(i=0; i<Children; i++)
	{
		Child[i].TellMe();
	}
}

bone* boneFindByID(bone *luu, unsigned int ID) // palauttaa osoittimeen haluttuun luuhun
{
	bone* u;

	if(!luu) return NULL; // tarkistetaan että luu on olemassa

	if(luu->GiveID() == ID) return luu;
	else
	{
		u = luu->FindByID( ID );
		if(!u) return NULL;
		else return u;
	}
}

bone* boneFindByName(bone *luu, const char *name) // palauttaa osoittimeen haluttuun luuhun
{
    bone* u;

    if(!luu) return NULL;

    if( strcmp(luu->GiveName() ,name) == 0 ) return luu;
    else
    {
        u = luu->FindByName( name );
        if(!u) return NULL;
        else return u;
    }
}

vektorit.hpp tiedostossa ainoa joka voi sekottaa on matriisien kiertomuodostajat
laitetaan nyt vielä vähä muutaki

vec3 :: vec3() // vektoriluokan muodostaja
{
    x=0.0; // kyllä! nämä on alustettu!
    y=0.0;
    z=0.0;
}

void mat4 :: RotX(const float angle)
{
    arvo[0]=1.0; arvo[4]=0.0;  arvo[8]=0.0; arvo[12]=0.0;
    arvo[1]=0.0; arvo[5]=cos(angle);  arvo[9]=sin(angle); arvo[13]=0.0;
    arvo[2]=0.0; arvo[6]=-sin(angle); arvo[10]=cos(angle); arvo[14]=0.0;
    arvo[3]=0.0; arvo[7]=0.0; arvo[11]=0.0; arvo[15]=1.0;
}

void mat4 :: RotY(const float angle)
{
    arvo[0]=cos(angle); arvo[4]=0.0;  arvo[8]=-sin(angle); arvo[12]=0.0;
    arvo[1]=0.0; arvo[5]=1.0;  arvo[9]=0.0; arvo[13]=0.0;
    arvo[2]=sin(angle); arvo[6]=0; arvo[10]=cos(angle); arvo[14]=0.0;
    arvo[3]=0.0; arvo[7]=0.0; arvo[11]=0.0; arvo[15]=1.0;
}

void mat4 :: RotZ(const float angle)
{
    arvo[0]=cos(angle); arvo[4]=-sin(angle);  arvo[8]=0.0; arvo[12]=0.0;
    arvo[1]=sin(angle); arvo[5]=cos(angle);  arvo[9]=0.0; arvo[13]=0.0;
    arvo[2]=0.0; arvo[6]=0; arvo[10]=1.0; arvo[14]=0.0;
    arvo[3]=0.0; arvo[7]=0.0; arvo[11]=0.0; arvo[15]=1.0;
}

esittelyt.hpp

class vec3
{
    public:
    float x, y, z;

    vec3();
    ~vec3();
    // ... muutaki löytyy
};

class mat4
{
    public:
    float arvo[16];

    // 0 4  8 12
    // 1 5  9 13
    // 2 6 10 14
    // 3 7 11 15

    void RotX(float angle); // Tekee matriisista X-akselin suhteen vektoria pyörittävän kulman angle verran
    void RotY(float angle); // Sama Y-akselille
    void RotZ(float angle); // Sama Z-akselille
};

class bone
{
	private:

	unsigned int ID; // tunnistenumero
	unsigned int Children; // lasten määrä
	bone *Child; // lapsi-osoitin

	mat4 dimension; // luun ulottuvuus alussa, "relatiivinen" parenttiin
	mat4 dimension_new; // luun ulottuvuus NYT, "absoluuttinen"

	vec3 Rot; // rotaatio, globaalien akseleiden ympäri!
	vec3 Pos; // positio, relatiivinen edelliseen boneen
	vec3 Scale; // skaalaus

	string name; // bonen nimi (tällä kertaa string!) :D jospa se toimisi

	public:

        bone();
	bone(unsigned int a, mat4 b); // id ja dimension
	~bone();

	bool AddChild(unsigned int bID, const char* bName, mat4 bDim); // lisätään lapsi

	void Free(); // tyhjennä lapset ja itsesi

	void SetDimension( mat4 a ); // aseta dimension
	void SetID( unsigned int a ); // aseta ID
	void SetName( const char *nimi ); // aseta nimi

	unsigned int GiveID(); // anna ID
	const char* GiveName(); // anna osoitin nimeen
	mat4 CalcDimension(); // anna ulottuvuus kierrettynä, skaalattuna ja translatoituna (relatiivinen parenttiin)
	mat4 GiveDimension(); // anna ulottuvuus NYT (absoluuttinen)
	mat4 getDimension(); // anna ihan alkuperäinen ulottuvuus

	vec3 GiveRotation(); // anna kierto (Rot)

	bone* FindByID(unsigned int f_ID); // palauta osoitin ID:n mukaan etsittyyn luuhun
    bone* FindByName( const char *name ); // sama mut etsi nimen mukaan

	void Rotate(); // laske lapsille uudet ulottuvuudet
	void Rotate( mat4 a ); // laske ulottuvuus kiertäen a:n verran

	int LoadSkeleton(const char *fileName); // lataa luuranko

	bool operator = (bone a); // kopiointi

	void TellMe(); // kerro asioita
};

Tämmöstä säätöä:D

Ohjelman käänsin näin:
g++ /home/tuomas/Ohjelmointi/bonetesti/main.cpp -o /home/tuomas/Ohjelmointi/bonetesti/ohjelma.o -g

Ja valgrindiä käytin näin:
valgrind --leak-check=yes --tool=memcheck --track-origins=yes /home/tuomas/Ohjelmointi/bonetesti/ohjelma.o

Jos jotain kiinnostaa katsoa ihan koko koodia nii seki onnistuu.

Metabolix [20.10.2010 19:14:03]

#

Koko koodi olisi kyllä kätevä, jos saat vaikka zippinä jonnekin. Mukaan vielä jokin esimerkkimalli tai mitä ohjelma ikinä tarvitseekin.

Suosittelen jo etukäteen muistin varaamista standardikirjaston vector-luokalla, niin tulee vähemmän virheitä. Jos joskus herää epäilys, että tuossa olisi pullonkaula, voit helposti vaihtaa jälkikäteen tilalle oman luokan, jossa on samanlainen rajapinta mutta joka käyttää suoraan new-operaattoria. Käytännössä nopeuseroa tuskin kuitenkaan on.

Sisuaski [20.10.2010 19:25:57]

#

Tämä tuskin ratkaisee varsinaista ongelmaasi, mutta ainakin yksi epäilyttävän näköinen kohta on funktio bone::CalcDimension, jossa matriisia b ei alusteta mitenkään ennen kuin sitä aletaan kertoa a:lla.

Mutta tosiaan kuten Metabolix sanoi, koko koodi kääntämiskelpoisessa muodossa helpottaisi virheen hakua.

Jokotai [20.10.2010 19:28:04]

#

Oletko kokeillut jollakin toisella koneella. Joskus on koneissa jokin muistipaikka jossain toisessa käytössä. Epäilykseni:
1. muistipaikka alustetaan ja sille annetaan arvo(kaikki hyvin)
2. joku ohjelma muuttaa muistipaikkaa(ongelma)
3. muistipaikka luetaan ja arvot ovat ihan outoja(seuraus)

Grez [20.10.2010 20:45:06]

#

Jokotai kirjoitti:

Oletko kokeillut jollakin toisella koneella. Joskus on koneissa jokin muistipaikka jossain toisessa käytössä.

Öh, miksi kannattaisi kokeilla toisella koneella, jos kerran ongelma esiintyy nykyiselläkin koneella? Se, että ohjelma sattumalta toimisi jossain toisessa koneessa, ei poistaisi bugia.

Missään nykyaikaisessa käyttöjärjestelmässä ei toiset ohjelmat muuttele sinun ohjelman muistipaikkoja.

Jokotai [20.10.2010 22:01:46]

#

Pitänee tutustua näihin nykyaikaisiin käyttöjärjestelmiin :)

Grez [20.10.2010 22:12:31]

#

Juu, kannattaa ihmeessä. Niitähän on mm Mac OS X, Linuxit, BSD:t, 98:a uudemmat WIndowsit (2000, XP, Vista, 7), OS/2, jne jne

verho88 [20.10.2010 23:54:21]

#

Sisuaskille: b-matriisi kyllä alustetaan. Se on oma luokkansa joka alustetaan aina kun se luodaan.

Mutta nyt on kaikki koodi saatavilla täältä: http://joose.servehttp.com/Bonetesti/bonetesti.zip

Mukana on myös skeleton.m3d-tiedosto, jota tarvitaan, että koko ohjelma edes toimii. (jos siis kääntämään haluaa ruveta) Tiedostomuoto on vähän oma muunnelma .obj-tiedostomuodosta, jotta sinne saadaan skeleton mukaan...

Grez [21.10.2010 00:26:03]

#

Jos toi on oikeaoppinen tapa koodata C++:aa, niin luojan kiitos en sillä paljon koodaile.

Tai oon ainakin kuvitellut että hpp:t olisi header-tiedostoja joihin ei kuulu laittaa koodia.

Sisuaski [21.10.2010 00:56:06]

#

Ongelman aiheuttaja taitaa olla tässä:

void mat4 :: operator=(mat4 a)
{
    unsigned int i;
    for (i=0; i<19; i++)
    {
        arvo[i]=a.arvo[i];
    }
}

Miten suuri taulukko arvo onkaan ja miten pitkälle sinne yritetään kirjoittaa?

verho88 [21.10.2010 00:56:08]

#

:D Eipä oo kukaan mulle opettanu sitä oikeaa tapaa:D Oon oppinu asioita nii miten oon oppinu, mut nyt ku ajattelen asiaa nii ehkä joku cpp-tiedosto vois olla fiksumpi missä suurin osa koodista olis..? Pitääpä ajan kuluks selvitellä et miten koodit mitäs levitellä eri tiedostoihin. Mut eipä se silti varmaan tota virhettä silti poistais mikä ohjelmassa sekoilee.

verho88 [21.10.2010 01:00:12]

#

Ei saa olla mahollista! Tässä käy aina näin. Joku tommone iha pikkuviba mitä ei hoksaa ku kattelee ihan muualle ja etsii virhettä toisaalta.. Ei nää metsää puilta. Joo kyllä nyt taas hävettää, heh:D Miten muuten tuli vaa mielee, et pitäskö jonku tommosen valgrindin tuo hoksata että mennään taulukosta yli vai? Ku ei se ainakaan mun käytöllä tuota hoksannu..

Kiitokset kyllä sulle Sisuaski! :)

Grez [21.10.2010 01:02:49]

#

Kato sisuaski oli nopeempi, olin just postaamassa samaa.

Mä vähän luulen, että valgrindinkin on vaikee huomata tuollaista, kun noi taulukot on vaan muistiosoitteita ja kuitenkin kaksi peräkkäistä muuttujaa on ihan yhtä lailla sun oman ohjelman muuttujia joita se saisi käpistellä ihan mielensä mukaan. Luulisin, että jos varaisit noi muistit dynaamisesti niin se varmaan jopa huomaisikin.

Vielä varmemmaksi vakuudeksi tuossahan on kyse heti ensimmäisestä esimerkistä kappaleesta "What won't Valgrind find" tuolta sivulta: http://www.cprogramming.com/debugging/valgrind.html

"Valgrind doesn't perform bounds checking on static arrays (allocated on the stack)."

Helpostihan tuon huomaa kun debuggerissa ajaa rivi kerrallaan koodia ja katsoo missä kohti virhe tapahtuu.

Metabolix [21.10.2010 11:34:58]

#

Ratkaisu ongelmaan olisi ollut debuggerin watch-toiminto, jolla saa ohjelman pysähtymään, kun tiettyyn muistiosoitteeseen kirjoitetaan.

verho88 kirjoitti:

Pitääpä ajan kuluks selvitellä et miten koodit mitäs levitellä eri tiedostoihin.

Asian taustoista kerrotaan tässä oppaassa, lue kokonaan. Oppaassa on myös pari linkkiä koodivinkkeihin, joissa asiaa käsitellään käytännössä.

Jtm [22.10.2010 01:28:16]

#

Grez kirjoitti:

Missään nykyaikaisessa käyttöjärjestelmässä ei toiset ohjelmat muuttele sinun ohjelman muistipaikkoja.

[offtopic]Olet oikeassa, eivät normaalitilanteessa :). Kuitenkin on olemassa ja on melko vaivatonta myös tehdä ohjelmia, jotka tarkoituksenomaisesti tutkivat ja muokkaavat muiden ohjelmien muisteja. Melko hyvä käytännön esimerkki on ohjelma Process Hacker. Anteeksi saivarteluni, koin tarpeelliseksi oikaista asian.[/offtopic]

Grez [22.10.2010 10:16:43]

#

En kyllä näe mitään tarvetta oikaisuun kun missään realistisessa tilanteessa mikään ohjelma ei muuttele juuri ohjelmoimasi, kääntämäsi ja käynnistämäsi ohjelman muistipaikkoja - joka on siis tilanne johon kommentoin.

Oikeastaan ainoa teoreettinen tilanne joka tulisi mieleen olisi, että joku olisi tehnyt koodareiden kiusaksi ohjelman, joka piinaa nimenomaan huomaamiaan uusia ohjelmatiedostoja. Yksi realistinen mahdollisus olisi buginen laiteajuri, mutta siinä tapauksessa luultavasti koko kone olisi melko epävakaa.

Toisen ohjelman muistialueelle kirjoittaminen vaatii kuitenkin (nykykäyttiksissä) sen verran vaivaa, että ihan vaan huonosti koodattu normisofta ei vahingossa sitä tee. Näinhän usein tapahtui vanhoissa moniajokäyttiksissä, jossa ohjelmien muistialueita ei voinut suojata. Eli täysin bugiton softa saattoi kaatua tai sekoilla, kun jokin buginen softa kirjoitti vahingossa sen muistialueelle.

Sitten hakkerointi ja esim. huijausohjelmat yleensä tarvitsee itse käynnistää ja käskeä tekemään jotain. Jopa troijalaiset ja sen sellaiset yleensä kohdistavat muuttelunsa joihinkin tiettyihin ohjelmiin, ei satunnaiseen itse tehtyyn softaan. Toki pienen pieni mahdollisuus, että troijalainen erehtyisi on tietenkin olemassa.


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta