Προς το περιεχόμενο

Συνάρτηση που επιστρέφει τη θέση του στοιχείου ενός πίνακα


lektikos

Προτεινόμενες αναρτήσεις

Το είπα ήδη ρε συ. Debug build και assert. Για την ακρίβεια δε χρειάζεται να το κάνεις manually, μπορείς απλά να γράψεις

assert(p);

Και αν είσαι σε debug build θα βγει dialog box που θα σου δίνει τη δυνατότητα να κάνεις break in στο debugger επιτόπου (τουλάχιστον στο VS). Try it. Αν είσαι σε release build => instacrash.

παπαρια. Δεν κανει break η παπαρια του vs... http://www.insomnia.gr/topic/506100-stl-%CF%84%CE%B7%CF%82-ms-%CE%BA%CE%B1%CE%B9-debug-error/

 

Δηλαδη κανει, αλλα δεν εχεις την callstack

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

  • Απαντ. 70
  • Δημ.
  • Τελ. απάντηση

Συχνή συμμετοχή στο θέμα

Δημοφιλείς Ημέρες

Συχνή συμμετοχή στο θέμα

Επίσης υπάρχουν (ή μπορείς να φτιάξεις μόνος σου) και macros που σε release build κάνουν expand σε no-op, αν είσαι σε performance critical σημείο και θέλεις maximum speed.

 

Update: δεν ξέρω γιατί και έχω πολύ καιρό να το κάνω ο ίδιος. Τελευταία φορά (δε θυμάμαι καν πότε ήταν) δούλευε κανονικότατα.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Οπα, το να βαλεις ενα τετοιο

void foo(void* p)
{
#ifdef DEBUG
	if(!p)
		MrDebugerBreakThatWithMessage("mpla mpla");
#endif
}
Μονο κακο δεν θα σου κανει. Βασικα αν δεν βαλεις κατι τετοιο μονο κακο θα σου κανεις.

 

Το χειρότερο που μπορεί να σου συμβεί (ειδικά ως επαγγελματία σε production code) δεν είναι ή μη ύπαρξη debugging mode (το οποίο το έχεις έτσι κι αλλιώς κλειστό στον τελικό σου κώδικα), αλλά να ακολουθείς την τακτική του defacer και στη release version του κώδικα σου, η οποία αφήνει να σκάνε τα exceptions και όποιον πάρει ο χάρος, να σκάσει στα χέρια του πελάτη αυτό που δεν σου είχε σκάσει σε 1.000.000 debug builds κατά το development και το beta testing, παίρνοντας παραμάζωμα π.χ. ότι unsaved είχε εκείνη την ώρα ή να αρχίζει να κάνει corrupt data στη μνήμη ή στο δίσκο μέχρι να σκάσει το seg-fault.

 

EDIT:

 

Όταν συμβεί κάτι τέτοιο (έξω από εδώ... όχι πως δεν έχει συμβεί :P) τότε πολύ θα γούσταρες να υπήρχε debugging mode στο API/library σου ώστε να εντοπίσεις ταχύτερα το πρόβλημα και να το διορθώσεις.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Το χειρότερο που μπορεί να σου συμβεί (ειδικά ως επαγγελματία σε production code) δεν είναι ή μη ύπαρξη debugging mode (το οποίο το έχεις έτσι κι αλλιώς κλειστό στον τελικό σου κώδικα), αλλά να ακολουθείς την τακτική του defacer και στη release version του κώδικα σου, η οποία αφήνει να σκάνε τα exceptions και όποιον πάρει ο χάρος, να σκάσει στα χέρια του πελάτη αυτό που δεν σου είχε σκάσει σε 1.000.000 debug builds κατά το development και το beta testing, παίρνοντας παραμάζωμα π.χ. ότι unsaved είχε εκείνη την ώρα ή να αρχίζει να κάνει corrupt data στη μνήμη ή στο δίσκο μέχρι να σκάσει το seg-fault.

 

Τακτική μου είναι να σου το επισημαίνω όταν λες μαλακίες, μιας και δεν έχεις πιάσει στα χέρια σου κώδικά μου και απλά τα βγάζεις όλα απ' το μυαλό σου. Επίσης τακτική μου είναι ο release κώδικας να έχει περάσει από unit tests, όπως και να μην αφήνω τη δυνατότητα σε τέτοια εφιαλτικά σενάρια να συμβούν. Θα έχεις δει ίσως προγράμματα όπως το Word που μπορεί να κρασάρουν αλλά στο relaunch σου δίνουν τη δυνατότητα για recovery. Newsflash: μπορείς να το κάνεις και συ.

 

Το να συνεχίσει το πρόγραμμα να εκτελείται μέχρι να σκάσει το segfault είναι ακριβώς αυτό που είπα πολύ νωρίτερα ότι ΔΕΝ πρέπει να γίνει (crash early), πράγμα που ενδεχομένως δεν πρόσεξες μέσα στην τσατίλα σου. Και ακριβώς αυτό που θα γίνει αν ακολουθήσει κανείς τις προτάσεις σου. Είναι προφανές και γνωστό σε όλους ότι από τη στιγμή που το πρόγραμμά σου έχει αρχίσει να "κάνει νερά", οτιδήποτε δοκιμάσεις να κάνεις μπορεί θεωρητικά να έχει απρόβλεπτες συνέπειες μιας και ήδη μία από τις υποθέσεις σου για το πώς συμπεριφέρεται το πρόγραμμα έχει καταρριφθεί. Αυτό πιθανότατα θα οδηγήσει (ή έχει ήδη οδηγήσει) στο να καταρριφθούν και άλλες, και κατ' επέκταση όλες. Επομένως crash early.

  • Like 1
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Και που λες πάπι, όταν σπάσει ο διάολος το ποδάρι του και (μετά από 1.000.000 debug builds και απροβλημάτιστο testing κατά το development) φτάσει κάποια στιγμή στα χέρια του πελάτη ο pEnd δείκτης να είναι off όταν περνιέται στη συνάρτηση του defacer, εφόσον δεν τον ελέγχει σε σχέση με τον pBegin, όχι μόνο είναι παραπάνω από πιθανό να μην εμφανιστεί early crash, αλλά είναι επίσης και παραπάνω από πιθανό να αρχίσει data corruption μέχρι να εμφανιστεί το crash (ίσως και κανά μισάωρο αργότερα) ίσως μάλιστα να μην εμφανιστεί και ποτέ crash.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

εφόσον δεν τον ελέγχει σε σχέση με τον pBegin

Το να συγκρίνεις δυο pointers για τους οποίους δεν ξέρεις τίποτα είναι undefined behavior. Το λέω μπας και σταματήσεις να εκτίθεσαι.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Εαν ο pEnd ειναι "off", τοτε δεν σε σωζει τιποτα. Πες οτι βαζεις error report στη find και σου πεταει ενα "error find: inv args". Και; Τι θα καταλαβεις με αυτο;

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Εαν ο pEnd ειναι "off", τοτε δεν σε σωζει τιποτα. Πες οτι βαζεις error report στη find και σου πεταει ενα "error find: inv args". Και; Τι θα καταλαβεις με αυτο;

Δεν είναι το error-report το θέμα, το θέμα είναι η συνάρτηση του API να σου κάνει flag το error με όποιον τρόπο έχει επιλέξει (errno, έξτρα όρισμα, ή ότι άλλο) έτσι ώστε εσύ ο end-programmer να μπορείς το κάνεις catch στον caller μετά την κλήση της συνάρτησης του API, και να πράξεις ανάλογα.

 

ΥΓ. Όσο για τα UB μεταξύ pointer comparisons, κοίτα πόσες προειδοποιήσεις σου δίνει ο compiler... εμένα μου γεμίζει 2 οθόνες ειδικά για αυτό το λόγο :lol:

 

int* find_next_equal_to(int* pBegin, int* pEnd, int needle) {
    while(pBegin < pEnd) {
        if (*pBegin == needle) return pBegin;
        ++pBegin;
    }
 
    return 0;
}

int main( void )
{
...
	int haystack[10] = { 1, 2, 3, 4, 5, 5, 4, 3, 2, 1 };
	int posfound[10] = {0};
	int needle = 4;
	int* pStart = haystack;

	while ( (pStart = find_next_equal_to(pStart, haystack + 20, needle)) ) {
		printf("Found at index %d: %d\n", pStart - haystack, *pStart);
		posfound[(int)(pStart - haystack)] = 1;
		++pStart;
	}
...
Επίσης μου κρασάρει κάθε 0.1ms :lol:

 

Άντε και καλή καρδιά... τα λέμε!

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Μ'αρεσει που "χωνεις" ενα bug, το οποιο ουτε με το δικο σου τροπο μπορεις να πιασεις. Οκ, πρεπει να κανουμε error reporting σε συναρτησεις οι οποιες δεν μπορουν να failρουν.... 

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Το να συγκρίνεις δυο pointers για τους οποίους δεν ξέρεις τίποτα είναι undefined behavior. Το λέω μπας και σταματήσεις να εκτίθεσαι.

 

Αντίθετα, αν ξέρεις πως είναι "μέσα στο ίδιο array" τότε όλα OK.

 

Αν δεν ήσουν τόσο εγκάθετος θα μπορούσες βασικά να κάνεις τη σύσταση ότι το < παρόλο που δεν είναι bug θα μπορούσε εξίσου καλά (καλύτερα?) να είναι !=. Αλλά ζητάω πολλά, το ξέρω.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Μ'αρεσει που "χωνεις" ενα bug, το οποιο ουτε με το δικο σου τροπο μπορεις να πιασεις.

Θα σου υπενθυμίσω πως σε αντίθεση με τον defacer δεν διαφήμισα τη δική μου πρόταση ως κατάλληλη για API, αλλά ως μια γρήγορη & εύκολη λύση.

 

Παρόλα αυτά, η δική μου υλοποίηση είναι bullet-proof στο bug στο οποίο αναφέρεσαι πολύ απλά διότι το μέγεθος του πίνακα δεν εξαρτάται από κανένα όρισμα της συνάρτησης... είναι ορισμένο ως σταθερά στον προεπεξεργαστή, και άρα κανένα runtime malfunction δεν μπορεί να το τροποποιήσει!

 

Επίσης είναι bullet-proof σε NULL reference exceptions. Τέλος έχει λίγες έως ελάχιστες πιθανότητες να προκαλέσει data corruption. Η μόνη somewhat sane τέτοια περίπτωση που μου έρχεται στο μυαλό είναι να αγνοήσεις το καταφανέστατο hint στη δήλωση της συνάρτησης πως o elems[] και ο posfound[] έχουν το ίδιο μήκος (αυτό δηλαδή που "έβγαλε το μάτι" του... έμπειρου defacer) και να περάσεις πίνακες με διαφορετικά μήκη.

 

That being said, εξακολουθεί να μην είναι κατάλληλη για API, αφού μεταξύ άλλων δεν διαχωρίζει την αποτυχία (δεν γράφτηκε για να ανήκει σε API, γράφτηκε στο πόδι για την ερώτηση του TS).

 

Οκ, πρεπει να κανουμε error reporting σε συναρτησεις οι οποιες δεν μπορουν να failρουν....

Τίποτα δεν είναι υποχρεωτικό!

 

Αλλά είναι τελείως διαφορετικό το να γράφεις συναρτήσεις API από το να γράφεις εσωτερικές συναρτήσεις ενός προγράμματος. Και μόνο ότι το user-base ενός API είναι κατά κανόνα απείρως μεγαλύτερο και πιο ανομοιογενές από το user-base ενός stand-alone προγράμματος, που σημαίνει πως σου κάνει απείρως δυσκολότερο το testing, αρκεί από μόνο του για να καταλάβει κανείς πως οι συναρτήσεις ενός API οφείλουν να είναι γραμμένες με στοιχειώδη σοβαρότητα.

 

Όταν λοιπόν εμφανίζεται ο defacer και μας πετάει μια διάτρητη από όποια πλευρά και να την πιάσεις συνάρτηση (βασικά την strchr()), και στο καπάκι μας λέει πως είναι η μοναδική καλή λύση έναντι των ήδη ποσταρισμένων και μας τη διαφημίζει ως ιδανική για να φτιάξεις οποιοδήποτε API πάνω της, ε είναι ολίγον τραγελαφικό.

 

Για τα υπόλοιπα γραφικά περί beyond stupidity, να του σκάσει στη μούρη του άσχετου που περνάει NULL ως όρισμα, τα παράπονά σου στο C committee για τη συμπεριφορά της strlen() κλπ, κλπ... τι να πω; Υποθέτω είναι χαρακτηριστικά του production code που παράγει, οπότε και τα υπερασπίζεται με τόση θέρμη, δεν μπορώ να σκεφτώ κάτι άλλο.

 

Κοντολογίς, ο καθένας μπορεί να φτιάξει τις API συναρτήσεις του όπως θέλει.... και το κάθε API θα τραβήξει το δρόμο του.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!

Δημιουργία νέου λογαριασμού

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα

  • Δημιουργία νέου...