» »

[c++]izpis spremenljivke naredi bistveno razliko

[c++]izpis spremenljivke naredi bistveno razliko

Ezekiel ::

Zdravo!

Imam integer tabelo, recimo glavna_tabela[2]...

nato preberem podatke v dve novi tabeli:

desna_tabela[0] = glavna_tabela[1];
leva_tabela[0] = glavna_tabela[0];

in naredim tmp[0] = desna_tabela[0] ^ leva_tabela[0];

sedaj pa problem...

v primeru, da izpišem katero od vrednosti v tabeli (katerokoli), zadeva deluje točno.
Če pa ne izpišem nobene vrednosti (ker ni potrebno), pa ne deluje. Ena od tabel dobi vedno neko čudno vrednost, čeprav jih pred uporabo resetiram (v zanki dam vse na 0)...

Kakšne ideje?

Gundolf ::

Le ena ideja - v kodi imaš bug.

Ezekiel ::

in kako naj ga najdem?

Oziroma, kaj sploh lahko vpliva na takšne zadeve? ...Glede na to, da samo izpisujem 8-O

Zgodovina sprememb…

  • spremenil: Ezekiel ()

Gundolf ::

To da izpisuješ ne vpliva na tabelce. Zadaj je nek drug bug, ki ga z izpisovanjem nekako omiliš. Kako bi ga ap našel pa ne vem. Lahko izbiraš med zelo veliko načini za debugiranje, odvisno je predvsem od kompleksnosti tvojega programa. Če je koda dovolj kratka in ni skrivnost jo lahko tudi obesiš sem gor.

jype ::

V enem if stavku imas prireditveni stavek, sem preprican.

Namesto operatorja (==) imas prireditev (=).

Ezekiel ::

Ok, zgodba je taka...

Imam število v binarni obliki, dolžine 2M. Zapisano je v tabeli integerjev. Tipi so template, da lahko poljubno menjam med short, long, ... Sedaj to število razbijem na pol, torej 2 dela po M bitov, levega obrnem in naredim XOR čez oba... Vse skupaj se dogaja v razredu NUMBER, M je dolžina števila, WORD_COUNT število potrebnih besed za zapis števila, WORD_SIZE pa je dolžina besed (16, 32, 64). Koda je sledeča:


void NUMBER<T>::fast_reduction_2part(){

        int new_M = M/2;
        int new_WORD_COUNT = new_M / WORD_SIZE + 1;
        
        //levi in desni del stevila
        T* left_part = new T[new_WORD_COUNT];
        T* right_part = new T[new_WORD_COUNT];

        //cout << right_part[0] << "\r";   //sicer ne dela

        //reset...
        for(int i = 0; i < new_WORD_COUNT; i++){
        	left_part[i] =  0;
        	right_part[i] = 0;
		}

	//desni del kar prepisemo
        for(int j = 0; j < new_WORD_COUNT; j++)right_part[j]=number[j];

	//ocistimo
	right_part[new_WORD_COUNT-1] &= (T)(pow(2.0,((new_M % WORD_SIZE)))-1);

	//zadevo shiftnemo za toliko v levo, da potem samo prepisemo ostale stevilke v levi del
        for(int i = 0; i < (WORD_SIZE - (new_M % WORD_SIZE)); i++)left_shift();

        //in prepisemo
        for(int k = 0; k < new_WORD_COUNT; k++){
			left_part[k] = number[(new_WORD_COUNT + k)];
	}

        //obracanje levega dela bit za bitom (preprosto ma deluje)

	T* tmp = new T[new_WORD_COUNT];
	for(int i = 0, j = new_M-1; i < new_M; i++, j--){
		tmp[i/WORD_SIZE] ^= ((left_part[j/WORD_SIZE] & (BIT << (j % WORD_SIZE)) ? 1 : 0) << (i % WORD_SIZE));
	}
	left_part = tmp;

	//XOR
        //number je kazalec na stevilo v razredu NUMBER
	for(int i = 0; i < new_WORD_COUNT; i++){
		number[i] = right_part[i] ^ left_part[i];
	}

        //spremenimo se ostale parametre razredu po spremembi
	M = new_M;
	WORD_COUNT = new_WORD_COUNT;
 }

Gundolf ::

Opazil sem naslednje:

  1. brezveze initializiraš left_part in right_part,

  2. imaš memory leake - moraš občasno klicat tudi delete, če že kličeš new,

  3. 2x, kjer je x integer se lahko izračuna takole:
    1 << x;


Na uč razen memory leakov ne vidim nič hujšega. Pri tem tvojem programu s kopico tabelic bi bil lahko problem da greš kje čez max index, samo iz kode tega ni videti.

OwcA ::

Kaj pa če je prevajalnik kje preveč entuzijastičen? Poskusi brez vsakršnih optimizacij.
Otroška radovednost - gonilo napredka.

Thomas ::

To je zagotovo tako, da imaš nekje v programu memory leak. Dodatna programska vrstica toliko spremeni iz tega izvirajoče konflikte, da se ne pokažejo ob istem času. Nek leak ti recimo ne popaca nič memorije ki jo rabiš, pač pa neko drugo področje.

jype ::

Skratka: napacno orodje. Uporabi taksnega, ki memory management dela namesto tebe, je z razvojnega stalisca bistveno ucinkovitejse.

Ce potem se vedno rabis hitrost pa potem kodo ki deluje prepisi v C oz. C++, bo tudi lazje.

Gundolf ::

Ta je pa dobra. Ne vem a je nekaterim garbage collector novo božanstvo al kaj :) Pointerji pa utelešenje hudiča. Sori Jype ampak tole mi je res tko smešno.

Ezekiel ::

torej,
- nepotrebne inicializacije sem odstranil (so bile bolj klic na pomoč)
- prevajalnik ni preveč entuziastičen (gcc version 3.2.3 (mingw special 20030504-1) ... že osnovno prevajanje pokvari vse
- bom pa stestiral še v drugem sistemu (Fedora, AMD64)
- iste težave sem imel že v C - ju, prav tako so stvari delovale šele po izpisu na zaslon...
- mogoče si program misli, "ah, dokler je ne vidi, ga ne zanima..."?

Ampak, sedaj pa še par vprašanj:
Če imaš en razred in v njemu spremenljivko, recimo tabelo števil int *
- kaj je hitrejše za manipulirat z njo: metoda ali zunanja funkcija?
- recimo, da bi rad spremenljivko spremenil, npr, vanjo bi rad zapisal drugo (izračunano) vrednost... Trenutna metoda je, da naredim novo spremenljivko, z njo manipuliram in na koncu rečem:

stara_spremenljivka = nova_spremenljivka;


(kot je razvidno v kodi). Ali obstaja boljši (bolj zdrav) način?

Memory leak je pa očitno prisoten, saj če dam v destruktor razreda

delete number


ne deluje pa popolnoma nič več.

Jezika pa ne bom menjal.... Je večji izziv odpravit napako...

DODANO: Sedaj še z izpisovanjem NE deluje več ;(

Zgodovina sprememb…

  • spremenil: Ezekiel ()

OwcA ::

kaj je hitrejše za manipulirat z njo: metoda ali zunanja funkcija?

Dokler nimaš virtual metod, bolj ali manj ni razlik.

recimo, da bi rad spremenljivko spremenil, npr, vanjo bi rad zapisal drugo (izračunano) vrednost... Trenutna metoda je, da naredim novo spremenljivko, z njo manipuliram in na koncu rečem:

Čemu nova spremenljivka? Dokler imaš enonitno kodo ali lokalno spremenljivko stem pridelaš le eno zaseganje pomnilnika ali pisanje na stack ter eno prireditev vrednosti.

Memory leak je pa očitno prisoten, saj če dam v destruktor razreda

delete number



ne deluje pa popolnoma nič več.

Če je number array moraš uporabiti operator delete[].
Otroška radovednost - gonilo napredka.

Zgodovina sprememb…

  • spremenilo: OwcA ()

Ezekiel ::

aha:

*** glibc detected *** corrupted double-linked list: 0x00000032eea2d6b8 ***

Gundolf ::

Če ti ne dela več lahko narediš en obsežen izpis za recimo vsako zanko v tem delu kode, ki si ga nalimal. Pa boš videl kje ti crasha oz. kje rezultat ni več pravilen. Seveda je lahko še boljša rešitev uporabiti debugger - ampak če delaš z velikimi tabelami včasih ni druge kot vse izpisat, magari v en file.

BigWhale ::

Corrupted stack.

Nekje pofedlas stack.

64202 ::

> *** glibc detected *** corrupted double-linked list: 0x00000032eea2d6b8 ***

Katera stvar ti pa to izpise?
I am NaN, I am a free man!

Ezekiel ::

zadevo izpiše, ko poženem program in pride do dotične funkcije...

emm, problem ni v zankah, saj če v trenutku, ko spremenljivko definiram, le to tudi izpišem (in dobim npr. vrednost 752)in potem dela. Če pa ne, pa ne.

Ah, saj ni pomembno, verjetno se selim v C >:D


Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

[C] Kazalčna aritmetika

Oddelek: Programiranje
293018 (1799) blay44
»

Pomoč pri programiranju z javo

Oddelek: Programiranje
203538 (2465) milc
»

.doc in .pdf v string

Oddelek: Izdelava spletišč
162047 (1646) DiTi
»

(Java)faktoriela

Oddelek: Programiranje
82021 (1752) kihc
»

delo z nizi

Oddelek: Programiranje
162971 (2515) tx-z

Več podobnih tem