C++ μυστήριο

Giorgos Keramidas keramida at ceid.upatras.gr
Wed Sep 17 17:28:45 EEST 2008


On Wed, 17 Sep 2008 14:57:39 +0300, Θοδωρής Λύτρας <thlytras at gmail.com> wrote:
> Θα ήθελα να μοιραστώ μαζί σας το παρακάτω μυστήριο:
>
> Παρατήρησα οτι η εφαρμογούλα που φτιάχνω σε C++ / Qt4 είχε ΔΙΑΦΟΡΕΤΙΚΗ
> συμπεριφορά όταν την εκκινούσα από κονσόλα από ότι όταν την εκκινούσα
> κλικάροντας το εικονίδιο του εκτελέσιμου μέσα από τον konqueror.

Και οι δύο είναι `valid' συμπεριφορές όμως.  Όπως λέει και ένα παλιό
comp.lang.c ανέκδοτο, όταν υπάρχει undefined behavior σε ένα πρόγραμμα
δεν είναι σωστό να παραπονιέσαι επειδή όταν το τρέχεις ξεπηδάνε nasal
demons από τη μύτη σου :P

> Ύστερα από debugging, εντόπισα το πρόβλημα σε ένα if statement το
> οποίο έλεγχε μια μεταβλητή bool, η οποία όμως δεν είχε αρχικοποιηθεί
> σε false.
>
> if (myBool)
> 	...	//is true
> else
> 	...	//is false
>
> Όταν το πρόγραμμα έτρεχε από κλικ, γινόντουσαν όσα έπρεπε να γίνουν σε
> περίπτωση false, όπως ακριβώς το ήθελα, παρ'ότι η μεταβλητή δεν είχε
> αρχική τιμή. Όταν το πρόγραμμα έτρεχε από κονσόλα, δε γινόταν απολύτως
> τίποτα από τα δύο!

Είναι πολύ πιθανόν να γίνεται με διαφορετικό τρόπο link το πρόγραμμα
όταν το τρέχεις μέσα από το KDE.  Επιλογές όπως το prelinking μπορεί να
αλλάζουν τη θέση, το padding, ή ακόμα και τη σειρά με την οποία
φορτώνονται κάποια μέρη του προγράμματος.  Ανάλογα με το πώς ακριβώς
έχει καταστρωθεί το runtime memory map του προγράμματος, οι δαίμονες που
λέγαμε διαλέγουν να βγουν είτε από από τα αυτιά σου είτε από τη μύτη
σου.  Και τα δύο είναι `bugs' όμως :)

> Το ερώτημα όμως είναι: γιατί το πρόγραμμα, ενώ έχει compilαριστεί με
> τον ίδιο ακριβώς τρόπο (g++) να εκτιμά διαφορετικά την μη
> αρχικοποιημένη bool μεταβλητή ανάλογα με το αν ξεκινά από κονσόλα ή με
> click από konqueror???  Και, ποιά είναι η "φυσιολογική" συμπεριφορά
> από τις 2? (Υποθέτω της κονσόλας... λιγότερο fault-tolerant)

Ένα ELF binary μπορεί να φορτωθεί με πολλούς διαφορετικούς τρόπους στη
μνήμη του τελικού process.  Κάτι που *μπορείς* να κάνεις είναι να βάλεις
ένα pause() call πριν το conditional.

Μόλις το πρόγραμμα σταματήσει, κάνε attach με ένα debugger πάνω του και
τύπωσε το memory map του και στη μία και στην άλλη περίπτωση.  Πιθανόν
να δεις γιατί στη μία περίπτωση τα uninitialized δεδομένα είναι `έτσι'
ενώ στην άλλη `αλλιώς'.



More information about the Linux-greek-users mailing list