Приветствую всех, коллеги!
Поставил Linux Slamd64 v 11 (64-разрядный клон Slackware). 32-битных версий библиотек не устанавливал. Весь софт, не шедший в поставке, собрал сам, все вроде бы нормально.
Пробую писать свою программу. Пользуюсь g++ 4.1.1, собирал сам. До определенного момента все идет нормально, но потом все начинает страшно глючить. Как все выглядит: в цикле есть проверка на значение переменной, которая отвечает за выход из цикла, вставил в цикл printf, который каждый шаг выводит на экран значение переменной. Так вот, условие НЕ ВЫПОЛНЯЕТСЯ, хотя выводимое на экран значение переменной соответствует условию выхода из цикла.Пример (код не весь, но смысл сохраняется):
int f; //Открытый ранее ПРАВИЛЬНЫЙ дескриптор
char buf[256];
int r; //Та самая переменная
/*Все переменные ЛОКАЛЬНЫЕ, описанные ВНУТРИ ф-ции*/for(;;)
{
r=some_func(f,buf);
/*DEBUG MESSAGE*/
printf("r=%d\n",r);
if(r) break; /*Не выполняющееся условие*/
}При первом-втором (иногда может быть до 5-6) вызове все правильно, а потом я вижу, что вывод на экран r=2, но цикл продолжает крутить.
И последнее: запускаюсь под gdb, ставлю точку останова, смотрю и тихо сползаю по стене
Стоим на строке if(r) break;
Мои действия
(gdb) ins r
$1 = 0(gdb) ins printf("r=%d\n",r)
2
$1 = 4Т.е. - printf выводит вроде бы верное значение переменной, но gdb видит почему-то 0, откуда он его блин берет, не пойму. И при выполнении условия тоже получается, что 0.
С памятью все нормально, проверено. Что за грабли, не пойму. Кто сталкивался?
ЗЫ:
Что заметил, адреса глобальных переменных, и динамически выделенной памяти 5-разрядные числа, а локальных переменных - 12 - разрядные, и все начинаются с 0x7fff.
>char buf[256];
> r=some_func(f,buf);
> if(r) break; /*Не выполняющееся условие*/
Что делает some_func() ? возможно портит стек>ЗЫ:
>Что заметил, адреса глобальных переменных, и динамически выделенной памяти 5-разрядные числа, а
>локальных переменных - 12 - разрядные, и все начинаются с 0x7fff.
>ну дык одни в куче, другие на стеке, нормально это.
>>char buf[256];
>> r=some_func(f,buf);
>> if(r) break; /*Не выполняющееся условие*/
>Что делает some_func() ? возможно портит стек
Ну, строго говоря, она не совсем такая, но смысл кода не потерялся.
Она читает из файла блок, обрабатывает его, и возвращает 0 без ошибки, 2 при конце файла, -1 при ошибке. Сама ф-ция some_func() проста как дверь, ничего военного не делает.
Она собрана в статическую либу, этот код я уже юзаю лет 5 без изменений. В 32-битных системах работает как часы.
Намекаю еще раз:
>char buf[256];> r=some_func(f,buf);
при переходе на 64 бит то что работало на 32 битах перестает работать достаточно часто.
Это не зависит от ее простоты или времени ее юзания на 32 битах. Так что либо код в студию либо смотрите что там у вас в ней эдакого :)
>Это не зависит от ее простоты или времени ее юзания на 32
>битах. Так что либо код в студию либо смотрите что там
>у вас в ней эдакого :)Вот кусок кода, в котором вылет
int load_record(int db)
{
int fd;
adb_descr* d;
int rd;
char __rhdr[2];
bool deleted=false;
memset(&__rhdr[0],0,2);
//Get DB descriptor struct
if(db<0) return ADBE_INVDESC;
d=(adb_descr*)__db_descr.get(db);
if(!d) return ADBE_INVDESC;
if(d->closed) return ADBE_INVDESC;
if(!d->count) return ADBE_EOF; //Empty database
d->deleted=false;
//Get file descriptor
fd=d->fd;
//Read record header
rd=read(fd,&__rhdr[0],2);
/*DEBUG*/
printf("rd=%d\n",rd);
/**** ЗДЕСЬ У НАС ГРАБЛИ ****/
if(rd!=2) return errno;
/** И ЧТО САМОЕ ИНТЕРЕСНОЕ, И ЭТО ПРОХОДИТ!!! ХОТЯ, ИЗ ФАЙЛА РЕАЛЬНО НИЧЕГО НЕ ПРОЧИТАНО!!!**/
if(memcmp(&rhdr[0],&__rhdr[0],2))
{
//Deleted record?
if(!memcmp(&dhdr[0],&__rhdr[0],2)) { d->deleted=true; deleted=true; goto _rdr; }
return ADBE_CORRUPTED;
}
_rdr:
rd=read(fd,d->rec.data,d->rec.len);
if(!rd) return ADBE_EOF; //End of file/** И ЭТО ТОЖЕ ПРОХОДИТ, СОБАКА БЕШЕНАЯ!!! **/
if(rd!=d->rec.len) return errno;
//Done
if(deleted) return ADBE_DELETED;
return 0;
}Мда. Только даже такой пример наврядли чего полнее скажет. Тогда придется приводить весь код, а там файлов штук 5 точно задействовано, хотя я не совсем уверен, может, и больше. Это либа статическая в итоге получается.
Блин, хоть в какую сторону копать, а то у меня мОзги уже плавятся...
Я вообще не пойму, КАК такое может быть?
Ну, если бы я стек попортил, так вылетело бы все, а оно РАБОТАЕТ!!! Я проверял, 3 часа цикл вертело, и ни одного сбоя сбоку или ошибки... Только вот, что делает, совсем непонятно...
Стоит попробовать натравить на этот код valgrind.
> d=(adb_descr*)__db_descr.get(db);
так и не узнали что же тут происходит((. тем более преобразование подозрительное.кстати, pragma pack используется?
> /** И ЧТО САМОЕ ИНТЕРЕСНОЕ, И ЭТО ПРОХОДИТ!!! ХОТЯ, ИЗ ФАЙЛА
>РЕАЛЬНО НИЧЕГО НЕ ПРОЧИТАНО!!!**/
откуда известно?
что strace грит?про valgrind уже сказали.
да, а если вместо:
rd=read(fd,&__rhdr[0],2);
printf("rd=%d\n",rd); /*DEBUG*/
if(rd!=2) return errno; /**** ЗДЕСЬ У НАС ГРАБЛИ ****/писать так:
if (rd = read(fd, __rhdr, 2)) != 2)
{
printf("debug --- fd %d rd = %d errno %d text error %s\n", fd, rd, errno, strerror(errno));
return errno;
}
то понятнее..и еще, подозрительные двойные подчеркивания в названиях переменных и функций, как бы с чем-нить не пересеклось (в коде или дебаггере :)
>Намекаю еще раз:
>>char buf[256];
>
>> r=some_func(f,buf);
>при переходе на 64 бит то что работало на 32 битах перестает
>работать достаточно часто.
>Это не зависит от ее простоты или времени ее юзания на 32
>битах. Так что либо код в студию либо смотрите что там
>у вас в ней эдакого :)Да чего мучаться заменить ее временно на вызов заглушки и проверить.
>>Намекаю еще раз:
>>>char buf[256];
>>
>>> r=some_func(f,buf);
>>при переходе на 64 бит то что работало на 32 битах перестает
>>работать достаточно часто.
>>Это не зависит от ее простоты или времени ее юзания на 32
>>битах. Так что либо код в студию либо смотрите что там
>>у вас в ней эдакого :)
>
>Да чего мучаться заменить ее временно на вызов заглушки и проверить.В заглушку поставить счетчик статик переменную, и на каждом двадцатом шаге возвращать 2 ку.или единицу.
>>>Намекаю еще раз:
>>>>char buf[256];
>>>
>>>> r=some_func(f,buf);
>>>при переходе на 64 бит то что работало на 32 битах перестает
>>>работать достаточно часто.
>>>Это не зависит от ее простоты или времени ее юзания на 32
>>>битах. Так что либо код в студию либо смотрите что там
>>>у вас в ней эдакого :)
>>
>>Да чего мучаться заменить ее временно на вызов заглушки и проверить.
>
>В заглушку поставить счетчик статик переменную, и на каждом двадцатом шаге возвращать
>2 ку.или единицу.точна :)
Спасибо всем! Разобрался.
Добавил в строку g++ к опции '-Wall' дополнительно '-Wextra -Werror'
Поправил код, пересобрал все, что было.
В итоге в выводе появились числа, размер которых не берусь сказать... Очень большие числа, в общем.
Начал копать с gdb и обнаружил-таки где на самом деле оказались грабли.
Есть у меня код, который писался еще в 1996г. Так там в описании одной структуры все целочисленные member-ы были либо long, либо unsigned long. А в функциях новых везде int-ами пользовался или unsigned int-ами. А в x86_64 оказывается, что размер long и long long 8 байт, а int - 4. А под x86 было наоборот, long и int 4 байта, а long long - 8. Я, честно говоря, только сегодня узнал, что так дела обстоят. Везде во всем ранее написанном коде позаменял нафиг все long на int и все сразу заработало как надо. Эх, как говорится, век живи, век учись... :)
>Везде во всем
>ранее написанном коде позаменял нафиг все long на int и все
>сразу заработало как надо.Молодца, продолжаем учится:
1) читаем МЕГА полезную ссылку про портирование на 64 бита:
http://www-128.ibm.com/developerworks/linux/library/l-port64...2) есть полезный файл stdint.h
содержит определения типов гарантированно имеющих нужный размер:
int8_t, int16_t, int32_t, int64_t и т.п. и соответствующие unsigned.
везде где только можно используем именно их. Никаких int или long, т.к. завтра наткнетесь на платформу с sizeof(int) == 8 и снова пляски с бубном.3) перечитываем С/С++ стандарты, отмечаем что типы int, long, char и т.п. определены не как равные столько то байт (char=1), а как больше(!!!) или равно (char >= 1). Чтоб знать какие еще сюрпризы нас ждут.
Удачи.