Directx Δημοσ. 5 Απριλίου 2012 Δημοσ. 5 Απριλίου 2012 Έχω φρικάρει φίλε DirectX με το συγκεκριμένο... ο 32μπιτος gcc του mingw λειτουργει κανονικά. Αργότερα που θα πάω σπίτι (εκεί έχω την 32μπιτη Pelles, εδώ έχω την 64μπιτη, που λειτουργεί σωστά) θα προσθέσω έναν εξτρα έλεγχο για errno != 0 στην f_size ... Λοιπόν, σε C++ Builder αφού μετακινηθώ με ένα fseek στην θέση LONG_MAX και ύστερα με ένα fgetc πάω πιο πέρα, σε αρχείο μεγέθους 2.149.797.568 bytes, τότε η ftell επιστρέφει μεν < 0 αλλά όχι το απόλυτο -1L της τεκμηρίωσης αλλά την αρνητική τιμή -2147483648 (oops! ) ενώ παράλληλα το errno δεν ενεργοποιείται (όπως όφειλε). Μόνος τρόπος για να διακόψω την διαπέραση του αρχείου (δίχως να το αφήσω να φτάσει σε EOF) είναι με μια συνθήκη < 0 και τίποτε άλλο. (βρε τι μαθαίνω ) Υ.Γ. Σε VS 2008 η ftell επιστρέφει -1L, όπως προβλέπεται από την τεκμηρίωση (η δε errno παραμένει ανενεργή).
migf1 Δημοσ. 5 Απριλίου 2012 Δημοσ. 5 Απριλίου 2012 Λοιπόν, σε C++ Builder αφού μετακινηθώ με ένα fseek στην θέση LONG_MAX και ύστερα με ένα fgetc πάω πιο πέρα, σε αρχείο μεγέθους 2.149.797.568 bytes, τότε η ftell επιστρέφει μεν < 0 αλλά όχι το απόλυτο -1L της τεκμηρίωσης αλλά την αρνητική τιμή -2147483648 (oops! ) ενώ παράλληλα το errno δεν ενεργοποιείται (όπως όφειλε). Μόνος τρόπος για να διακόψω την διαπέραση του αρχείου (δίχως να το αφήσω να φτάσει σε EOF) είναι με μια συνθήκη < 0 και τίποτε άλλο. (βρε τι μαθαίνω ) Την οποία συνθήκη εγώ (ο καημένος ) την έχω εξαρχής ΥΓ. Το άνοιξες ως binary το αρχείο πριν ζητήσεις ftell; Ρωτάω γιατί στη θεωρία για text-files η ftell έχει undefined behaviour.
Directx Δημοσ. 5 Απριλίου 2012 Δημοσ. 5 Απριλίου 2012 Την οποία συνθήκη εγώ (ο καημένος ) την έχω εξαρχής ΥΓ. Το άνοιξες ως binary το αρχείο πριν ζητήσεις ftell; Ρωτάω γιατί στη θεωρία για text-files η ftell έχει undefined behaviour. Yeap, ως "rb". Υ.Γ. Κοίταξε, και σε C++ Builder αφού γυρίζω σε αρνητική τιμή (0χFF...) αντί του -1 που δίνει το VS08 δεν αποκλείεται για κάποιο πολύ μεγαλύτερο αρχείο από αυτό που δοκίμασα να γυρίσει κάποια στιγμή και σε θετική τιμή οπότε "μια από τα ίδια".
migf1 Δημοσ. 5 Απριλίου 2012 Δημοσ. 5 Απριλίου 2012 Nice Στην Pelles32 πάντως είτε κάνω cast αργότερα είτε δεν κάνω καθόλου στην επιστροφή της ftell() δεν επιστρέφει αρνητικό αριθμό ποτέ. Συμπεριφέρεται σαν να είναι unsigned long και κάνει wrap-around. Αν δηλαδή της περάσω ένα αρχείο π.χ. 5.3Gb μου απαντάει πως είναι 1.7Gb Υ.Γ. Κοίταξε, και σε C++ Builder αφού γυρίζω σε αρνητική τιμή (0χFF...) αντί του -1 που δίνει το VS08 δεν απολύεται για κάποιο πολύ μεγαλύτερο αρχείο από αυτό που δοκίμασα να γυρίσει κάποια στιγμή και σε θετική τιμή οπότε "μια από τα ίδια". Το γαμότο είναι πως αυτή η συνάρτηση είναι ο μοναδικός portable κώδικας για να πάρεις το μέγεθος ενός αρχείου. Την χρησιμοποιώ στον hexviewer ώστε αρχεία μικρότερα του LONG_MAX να γίνοnται malloc'ed μονοκόμματα, ενώ για τα μεγαλύτερα (όταν δλδ η f_size() επιστρέφει 0) κάνω malloc σε τμήματα με realloc ...οπότε το συγκεκριμένο πρόβλημα μου έχει καταστρέψει όλο το κόνσεπτ. Εν τω μεταξύ, το run-time της Pelles-C μπορεί και κάνει realloc πολύ μεγαλύτερα τμήματα μνήμης από ότι του mingw-gcc (που χρησιμοποιεί νομίζω του vs)... αυτό τα παίζει περίπου στο 1.5Gb (με τμήματα των 100Mb) ... η Pelles-C μου έκανε μέχρι 3Gb πριν τα φτύσει. γαμώ τον portable κώδικα μέσα γαμώ
REDODIN7 Δημοσ. 5 Απριλίου 2012 Δημοσ. 5 Απριλίου 2012 3.Όποτε τρέχω ένα πρόγραμμα,το αποτέλεσμα εμφανίζεται για λίγο και μετά σβήνει.Ποια εντολή μπορώ να χρησιμοποιήσω για να το αποτρέψω; Ελπίζω να μην έγινα κουραστικός.Ευχαριστώ προκαταβολικά. Μπορεις να χρησιμοποιησεις την εντολη system("pause");
imitheos Δημοσ. 5 Απριλίου 2012 Δημοσ. 5 Απριλίου 2012 Nice Στην Pelles32 πάντως είτε κάνω cast αργότερα είτε δεν κάνω καθόλου στην επιστροφή της ftell() δεν επιστρέφει αρνητικό αριθμό ποτέ. Συμπεριφέρεται σαν να είναι unsigned long και κάνει wrap-around. Αν δηλαδή της περάσω ένα αρχείο π.χ. 5.3Gb μου απαντάει πως είναι 1.7Gb Σίγουρα συμπεριφέρεται διαφορετικά από ό,τι θα περιμέναμε αλλά δεν είναι απαραίτητα λάθος αυτή η συμπεριφορά. Η ftell πρέπει να επιστρέψει το offset εκτός και ΑΝ αποτύχει οπότε επιστρέφει -1. Αν κρίνουμε από αυτό που λες ότι παίζει για 5.3GB (το οποίο είναι μεγαλύτερο και από unsigned 32bit) τότε ίσως εσωτερικά οι συναρτήσεις να χρησιμοποιούν 64bits (κάτι σαν το _FILE_OFFSET_BITS=64 της glibc) οπότε τυπικά η ftell "επιτυγχάνει" άρα δεν επιστρέφει -1 αλλά την τιμή η οποία γίνεται wrap. Εννοείται πως δεν έχω στοιχεία για την συμπεριφορά που περιγράφω και μπορεί να δουλεύει τελείως διαφορετικά.
migf1 Δημοσ. 5 Απριλίου 2012 Δημοσ. 5 Απριλίου 2012 Σίγουρα συμπεριφέρεται διαφορετικά από ό,τι θα περιμέναμε αλλά δεν είναι απαραίτητα λάθος αυτή η συμπεριφορά. Η ftell πρέπει να επιστρέψει το offset εκτός και ΑΝ αποτύχει οπότε επιστρέφει -1. Αν κρίνουμε από αυτό που λες ότι παίζει για 5.3GB (το οποίο είναι μεγαλύτερο και από unsigned 32bit) τότε ίσως εσωτερικά οι συναρτήσεις να χρησιμοποιούν 64bits (κάτι σαν το _FILE_OFFSET_BITS=64 της glibc) οπότε τυπικά η ftell "επιτυγχάνει" άρα δεν επιστρέφει -1 αλλά την τιμή η οποία γίνεται wrap. Εννοείται πως δεν έχω στοιχεία για την συμπεριφορά που περιγράφω και μπορεί να δουλεύει τελείως διαφορετικά. Λίγο "χλωμό" το βλέπω να παίζει κάτι τέτοιο, γιατί είναι δηλωμένη ως long int η ftell (off_t είναι η ftello, που στην pelles είναι _off_t & _ftello(), ως extension... που πράγματι δεν είναι στάνταρ συναρτήσεις αυτές). Θα δοκιμάσω πάντως να αναθέσω απευθείας την ftell() σε έναν uintmax_t για να επιβεβαιώσουμε/διαψεύσουμε αυτό που σκέφτηκες.
imitheos Δημοσ. 5 Απριλίου 2012 Δημοσ. 5 Απριλίου 2012 Λίγο "χλωμό" το βλέπω να παίζει κάτι τέτοιο, γιατί είναι δηλωμένη ως long int η ftell (off_t είναι η ftello, που στην pelles είναι _off_t & _ftello(), ως extension... που πράγματι δεν είναι στάνταρ συναρτήσεις αυτές). Θα δοκιμάσω πάντως να αναθέσω απευθείας την ftell() σε έναν uintmax_t για να επιβεβαιώσουμε/διαψεύσουμε αυτό που σκέφτηκες. Ναι φυσικά είναι δηλωμένη να επιστρέφει long. Αυτό που εννοούσα είναι πώς υλοποιείται η συνάρτηση ασχέτως τι επιστρέφει. Για παράδειγμα στο linux που δοκίμασα να δω τι επιστρέφει, επιστρέφει μεν -1 και EOVERFLOW αλλά μόνο αν έχω κάνει compile με _FILE_OFFSET_BITS=64. Διαφορετικά δεν ανοίγει καν το αρχείο η fopen.
migf1 Δημοσ. 5 Απριλίου 2012 Δημοσ. 5 Απριλίου 2012 Ναι φυσικά είναι δηλωμένη να επιστρέφει long. Αυτό που εννοούσα είναι πώς υλοποιείται η συνάρτηση ασχέτως τι επιστρέφει. Για παράδειγμα στο linux που δοκίμασα να δω τι επιστρέφει, επιστρέφει μεν -1 και EOVERFLOW αλλά μόνο αν έχω κάνει compile με _FILE_OFFSET_BITS=64. Διαφορετικά δεν ανοίγει καν το αρχείο η fopen. Σε λίγο που θα πάω σπίτι, θα φτιάξω ένα πρόχειρο test-prog που να εφαρμόζει την f_size() στο 1ο του command-line argument και να τυπώνει το μέγεθος (και θα επανέλθω... υπολογίστε καμιά ωρίτσα... ίσως και παραπάνω... μέχρι να πάω σπίτι, να κάνω μπανάκι και να φάω )
migf1 Δημοσ. 5 Απριλίου 2012 Δημοσ. 5 Απριλίου 2012 Έκανα κάθε πιθανό κι απίθανο συνδυασμό που θα μπορούσα να σκεφτώ, χωρίς επιτυχία... > #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include <inttypes.h> #include <errno.h> /*********************************************************//** * ************************************************************* */ bool f_exists(const char *fname) { FILE *fp = fopen(fname, "rb"); if ( !fp ) return false; fclose(fp); return true; } /*********************************************************//** * @brief Return the size of a file in bytes, or 0 on error * (cannot be more than LONG_MAX). ************************************************************* */ uintmax_t f_size( const char *fname ) { long long int size = 0; FILE *fp; if ( NULL == (fp = fopen(fname, "rb")) ) /* binary mode */ return 0; if ( 0 != fseek(fp, 0L, SEEK_END) ) { fclose(fp); return 0; } size = (long long int)ftell(fp); perror(NULL); printf( "size = %lld\n", size ); fclose(fp); return (errno != 0 || size < 0) ? 0 : (uintmax_t)size; } /* --------------------------------------------------------------------------------- */ int main( int argc, char *argv[] ) { // uintmax_t fsize = 0; if ( 1 == argc ) { fputs( "*** no data!\n", stderr ); goto ret_fatal; } if ( !f_exists(argv[1]) ) { fputs( "*** non-existent file!\n", stderr ); goto ret_fatal; } printf( "file size: %"PRIuMAX"\n", f_size(argv[1]) ); system("pause"); /* windows only */ exit(EXIT_SUCCESS); ret_fatal: system("pause"); /* windows only */ exit(EXIT_FAILURE); } Έχω αφήσει μια δοκιμή με long long int στον κώδικα της f_size. Ότι και να κάνω, κάνει wrap around (τελικά ο mingw32 gcc κάνει fail() στην fseek για αρχεία μεγαλύτερα του LONG_MAX, και όχι στην ftell() που έγραψα σε προηγούμενα post... δεν φτάνει καν στην ftell() )
migf1 Δημοσ. 6 Απριλίου 2012 Δημοσ. 6 Απριλίου 2012 Το πρόβλημα είναι πως αυτό ο κώδικας της f_size() είναι ο μόνος portable σε όλες τις πλατφόρμες φίλε DirectX.
Timonkaipumpa Δημοσ. 6 Απριλίου 2012 Δημοσ. 6 Απριλίου 2012 Θες να πεις ότι εσείς δεν έχετε κολλημένο στο γραφείο ένα χαρτάκι με τα promotions και άλλο με operator precedence ? Το οποίο είναι κολλημένο πάνω από χαρτάκι για συντομεύσεις (vi, emacs κτλ) που, αραιά και που, το σηκώνουμε λίγο για να δούμε από κάτω :D
Directx Δημοσ. 6 Απριλίου 2012 Δημοσ. 6 Απριλίου 2012 Το πρόβλημα είναι πως αυτό ο κώδικας της f_size() είναι ο μόνος portable σε όλες τις πλατφόρμες φίλε DirectX. Φίλε migf1 δεδομένης της κατάστασης όμως θα μπορούσες να βασιστείς σε *συναρτήσεις POSIX, οι οποίες αν δεν υποστηρίζονται συνολικά από τις πιο γνωστές πλατφόρμες, οπωσδήποτε παρέχουν υποστήριξη στις πιο βασικές , όπως για παράδειγμα η stat η οποία μεταξύ άλλων επιστρέφει το μέγεθος του αρχείου (και σε BC++ επιστρέφει επίσης αρνητική τιμή για MAX_LONG + 1 μεγέθους αρχεία). *Επίσης ρίξε μια ματιά και στις ρουτίνες fsetpos/ fgetpos, για παράδειγμα σε BC++, πάω με fseek στο MAX_LONG του αρχείου, μετακινούμε +1 θέση και ύστερα λαμβάνω την θέση με fgetpos. Το fpos_t είναι μορφής LONG (σε BC++ πάντα) οπότε έχει γυρίσει σε αρνητική τιμή, δες αν συμβαίνει το ίδιο στους compiler σου. Επίσης δοκίμασε και την fsetpos μήπως έχεις καλύτερα αποτελέσματα. *Αυτά με την ελπίδα ότι εσωτερικά δεν καταλήγουν σε κάποιο ftell/fseek κλπ. Υ.Γ. Εγώ στην θέση σου, θα καλούσα σε LL επίπεδο συνάρτηση του Λ.Σ. και όποιος ήθελε, κατά το port, ας πρόσφερε την ανάλογη συνάρτηση του δικού του Λ.Σ. -μέχρι ότου οι συναρτήσεις της C διορθωθούν. Το έχω δει ως πρακτική σε αρκετά Open Source projects που έχουν γίνει port σε πολλές πλατφόρμες.
Προτεινόμενες αναρτήσεις