The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]



Вариант для распечатки  
Пред. тема | След. тема 
Форум Программирование под UNIX (C/C++)
Режим отображения отдельной подветви беседы [ Отслеживать ]

Оглавление

C/C++ 64bit. Глюк при сравнении чисел, yerdna (ok), 24-Ноя-08, (0) [смотреть все]

Сообщения [Сортировка по времени | RSS]


11. "C/C++ 64bit. Глюк при сравнении чисел"  +/
Сообщение от yerdnaemail (ok), 28-Ноя-08, 12:05 
>>size_t lSize, result;
>>...
>>lSize = ftell (pFile);
>
>Попробуй еще
>
>off_t lSize;
>...
>lSize = ftello (pFile);

Пробывал, ничего не изменилось.

>Количество считанных из файла байт потрясает. Дайте мне два таких винта :)
>Переменные типа size_t выводи с форматом %zu

И при таком раскладе все тоже самое
result = 18446744071619674112

>И включить -Wall чтобы gcc на printf() вываливал варнинг по поводу несоответствия >спецификатора и типа выводимого значения.

Все соответствует, Wall молчит как рыба.

----------
Повторюсь:
все работает так как надо, ошибки не выскакивают, то что я загрузил в память я потом с легкостью записываю обратно на винт, без всяких потерь данных.
Просто выскакивает такой глюк, если размер файла больше ~2гиг.
Единственный минус, так это то, что нельзя проверить сколько он считал.
Но как вариант я уже думаю просто форматировать result через sprintf c %u.

Кстати где-то вычитал, что feof() в таком месте не будет работать в любом случаи.
Весь инет облазил, толком ничего и не нашел как исправить этот глюк с fread.

Ответить | Правка | Наверх | Cообщить модератору

12. "C/C++ 64bit. Глюк при сравнении чисел"  +/
Сообщение от vic (??), 28-Ноя-08, 14:29 
>[оверквотинг удален]
>>>...
>>>lSize = ftell (pFile);
>>
>>Попробуй еще
>>
>>off_t lSize;
>>...
>>lSize = ftello (pFile);
>
>Пробывал, ничего не изменилось.

fseeko() & ftello() одновременно, одного не достаточно (ессно с off_t).

тип фс? для теста что будет если ручками в шелле создать файл >2GB и скопировать его?

т.к. у вас фря, а у меня линукс, проверить я на коленке ничего не могу, но могу посмотреть ман для фри выложенный на опеннет, вижу что возвращаемое/устанавливаемое значение оффсета имеет тип long (возможно ман на опеннете безнадежно устарел), а не size_t. off_t судя по замечаниям в других манах (для lseek русский ман здесь же на опеннете) может быть int (4 byte, !8 byte), а lseek используется в fseek. Т.е. необходимо с файлами более 2 ГБ очень аккуратным. где-то все же ошибка у нас с вами, даже если кажется что считывается все вроде бы правильно...

переменная errno после каждой операции проверяется?

Ответить | Правка | Наверх | Cообщить модератору

13. "C/C++ 64bit. Глюк при сравнении чисел"  +/
Сообщение от Michelnok (??), 28-Ноя-08, 16:03 
> но могу посмотреть ман для фри выложенный на опеннет

В этом отношении с FreeBSD хорошо:
http://www.freebsd.org/cgi/man.cgi

Ответить | Правка | Наверх | Cообщить модератору

14. "C/C++ 64bit. Глюк при сравнении чисел"  +/
Сообщение от Michelnok (??), 28-Ноя-08, 16:13 
>>Переменные типа size_t выводи с форматом %zu
>
>И при таком раскладе все тоже самое
>result = 18446744071619674112

Если это действительно сразу после fread (т.е. ты совсем ничего не делаешь с result), то похоже таки на ошибку в libc. Точнее, в твоей ее версии.

Ответить | Правка | К родителю #11 | Наверх | Cообщить модератору

15. "C/C++ 64bit. Глюк при сравнении чисел"  +/
Сообщение от yerdnaemail (ok), 28-Ноя-08, 21:24 
Наконец-то выяснил в чем проблема!) Конечно же не без вашей помощи, всем спасибо, особенно Michelnok и vic!!!

Рассказываю в чем проблема:

>Если это действительно сразу после fread (т.е. ты совсем ничего не делаешь
>с result), то похоже таки на ошибку в libc. Точнее, в
>твоей ее версии.

После этого поста, я решил проверить, что же на самом деле делает fread.
Открыл /usr/src/lib/libc/stdio/fread.c и что я вижу

.........
size_t
fread(void * __restrict buf, size_t size, size_t count, FILE * __restrict fp)
{
        int ret; //ВНИМАНИЕ СЮДА

        FLOCKFILE(fp);
        ret = __fread(buf, size, count, fp);
        FUNLOCKFILE(fp);
        return (ret); //ВНИМАНИЕ СЮДА
}

size_t
__fread(void * __restrict buf, size_t size, size_t count, FILE * __restrict fp)
{
        size_t resid;
        char *p;
        int r; //ВНИМАНИЕ СЮДА
        size_t total;

        /*
         * The ANSI standard requires a return value of 0 for a count
         * or a size of 0.  Peculiarily, it imposes no such requirements
         * on fwrite; it only requires fread to be broken.
         */
        if ((resid = count * size) == 0)
.........
        while (resid > (r = fp->_r)) {
                (void)memcpy((void *)p, (void *)fp->_p, (size_t)r);
                fp->_p += r;
                /* fp->_r = 0 ... done in __srefill */
                p += r;
                resid -= r; //ВНИМАНИЕ СЮДА
                if (__srefill(fp)) {
                        /* no more input: return partial result */
                        return ((total - resid) / size);
                }
        }
.........
        return (count);
}
-----------------------
что функция возвращает переменную типа int, ХОТЯ в функции объявленно, что возвращаем тип size_t, отсюда понятно почему файлы больше 2гиг, а это больше 2 147 483 648, возвращал что-то страшное.
После исправления int на size_t, все заработало.
Често говоря, я удивлен, что разработчики freebsd допустили такую ошибку(size_t -> int).

Ответить | Правка | Наверх | Cообщить модератору

16. "C/C++ 64bit. Глюк при сравнении чисел"  +/
Сообщение от Michelnok (??), 28-Ноя-08, 22:01 
>[оверквотинг удален]
>        int ret; //ВНИМАНИЕ СЮДА
>
>
>        FLOCKFILE(fp);
>        ret = __fread(buf, size,
>count, fp);
>        FUNLOCKFILE(fp);
>        return (ret); //ВНИМАНИЕ СЮДА
>
>}

Ужас.

Ответить | Правка | Наверх | Cообщить модератору

Архив | Удалить

Рекомендовать для помещения в FAQ | Индекс форумов | Темы | Пред. тема | След. тема




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру