Автор Тема: Малък въпрос за lseek()  (Прочетена 6020 пъти)

remotex

  • Напреднали
  • *****
  • Публикации: 344
    • Профил
Re: Малък въпрос за lseek()
« Отговор #15 -: Aug 29, 2012, 23:34 »
(off_t)(-10) ще ти го направи 64 битово -10 т.е.
(off_t)(-10) == 0x FFFF FFFF FFFF FFF6
(int)(-10) == 0x FFFF FFF6

тогава gcc ще не ще - ще извика правилната функция (64 битова вместо 32) т.е. вместо %еsi ще ползва %rsi което няма да го отреже поради незнание
 от  0x FFFF FFFF FFFF FFF6
 на  0x FFFF FFF6 което предполагам после неправилно се разширява
 до  0x 0000 0000 FFFF FFF6 (това нещо и със и без знак все си е 4,294,967,286)
понеже signed register нема там всичко е unsigned :-) т.е. най-вероятно въобще не се разширява (пак добре че регистъра явно изначално е занулен при/преди викането на функцията) - прочете ли статията за коня дето можел да говори, а?! :-)
правилното разширение би било отново
 до  0x FFFF FFFF FFFF FFF6
но понеже процесора не знае за какво иде реч..
Затова се използва SAR вместо SHR напр. защото прави същото което ще направи и (off_t)(-10) в сл. запазва и размножава знаковия бит и освен това и кара gcc да свърже правилната 64 битова функция - цяло чудо е че намира с нещо да свърже без явно указан unistd.h - за съжаление явно това не е правилното нещо - нормално ако вижда 2 варианта на lseek единствения параметър по който да ги различи ми се вижда баш отместването т.е. предолагам при следните прототипи на функцията:
lseek(int, int, int) // 32 bit
lseek(int, long int, int) // 64 bit
и ти му излизаш със следната постановка (при 64 битова ОС)
lseek(int, int, int) // -10
или
lseek(int, long int, int) // (off_t)(-10)
Как мислиш кога коя функция ще match-ва ;-)

Естествено пробвах преди да пиша първия път и при мен даде резултат - с Федора 17 64 бит съм

(int32_t)(-10) == 0x FFFF FFF6 == -10
(uint32_t)(-10) == 0x FFFF FFF6 == 4,294,967,286
обаче интерпретацията на последните 2 е различна -10 / 4,294,967,286

П.П. Една причина поради която 32 битова функция () може да ползва 64 битов или unsigned offset e
LFS
gcc -D_FILE_OFFSET_BITS=64
http://en.wikipedia.org/wiki/Large_file_support
Many old interfaces, especially C-based ones, explicitly specified argument types in a way that did not allow straightforward nor transparent transition to 64-bit types. For example, the C functions fseek and ftell operate on file positions of type long int, which is typically 32 bits wide on 32-bit architecture, and cannot be made larger without sacrificing backward compatibility. (This was resolved by introducing new functions fseeko and ftello. On Windows machines, under Visual C++, functions _fseeki64 and _ftelli64 are used.)
« Последна редакция: Aug 29, 2012, 23:56 от remotex »
Активен

gat3way

  • Напреднали
  • *****
  • Публикации: 6050
  • Relentless troll
    • Профил
    • WWW
Re: Малък въпрос за lseek()
« Отговор #16 -: Aug 30, 2012, 03:58 »
Струва ми се че малко превратно сте разчели асемблерния код. Няма "32-битова" и "64-битова" версия на функцията в двата листинга, става въпрос за една и съща функция и за 64-битов код. Според AMD64 calling конвенцията, първия аргумент на функцията  трябва да е в rdi, втория - в rsi, третия - в rdx и така нататък. Това което предполагам е изрязано от копи-пейста, някъде по-нагоре е зануляването на rsi,rdi и rdx. Предполагам ако shoshon погледне пак ще открие нещо от сорта на xor %rsi,%rsi и xor %rdi,%rdi по-нагоре.

Сега защо във втория случай параметъра се предавал през esi, а не през rsi - esi е просто младшата "половинка" на rsi. Сега няма значение ако присвояваме на rsi някаква 32-битова стойност дали ще правим (при занулен rsi) mov xxx,rsi или mov xxx,esi, но второто си има предимства.  Има няколко причини за това - инструкцията е "по-къса" заради по-"късата" литерална стойност и следователно се кодира с по-малко байта, мисля че това е видимо в листинга. Това си има performance предимства - по-добра утилизация на instruction кеша, по-добра утилизация на pipeline-а и така нататък. Допълнително, "по-късите" инструкции дават на компилатора повече свобода да си align-ва кода и това също има значение.

Ако все още се съмнявате в горното, вижте как се предава  третия аргумент в rdx - флага, който е unsigned int, демек 32-битов. И в двата случая се присвоява на edx, не на rdx. Алтернативно същото става и с първия аргумент на lseek() -  32-битовия файлов дескриптор - предава се през edi, не през rdi.

Така че не става въпрос за 32-битова и 64-битова функция, и двете са една и съща 64-битова.

Това което не мога да разбера е защо без unistd.h, компилатора решава че off_t аргумента е 32-битов, а не както трябва да е - 64-битов. Това което мога да кажа със сигурност е че компилаторът не прави имплицитно кастване на литералната стойност към unsigned такава, това би било безумно, най-малкото при това положение, щеше да е много добре известен проблем (много хора щяха да изреват с отрицателни литерални стойности и константи, не мислите ли? :) ).

Предполагам отговора се крие някъде из unistd.h или по-скоро някъде из включените от него хедъри нейде из asm/<arch>/bits/... Обаче това са толкова добре навързани спагети, че човек трябва да има извънредно здрави нерви да се зарови в това :)
« Последна редакция: Aug 30, 2012, 05:23 от gat3way »
Активен

"Knowledge is power" - France is Bacon

remotex

  • Напреднали
  • *****
  • Публикации: 344
    • Профил
Re: Малък въпрос за lseek()
« Отговор #17 -: Aug 30, 2012, 19:33 »
Да де и аз това имах предвид че се вика функция с 32 битов параметър - което ако беше 32 битова ОС нямаше да е проблем щото нямаше да се налага разширяване на числовия литерал който се подава. Просто може-би малко по-неясно съм се изразил ама то от бързане щото съм доста зает тия дни ..и от старост вече може-би...  :'(

Не смятам че оптимизацията на gat3way е валидна в случай като нашия когато се вика код от друг модул /библиотечна функция/ по принцип такива оптимизации са възможни само в/върху един и същи т.нар. translation unit или 1 файл или хайде проект да го наречем - само когато и извикващата и извикваната функция се компилират от същия компилатор и той знае какво да очаква и от двете страни. В случая с викането на библиотечна ф-я или изобщо код от друг translation unit компилатора няма как да знае онова чудо(вище) отсреща как е компилирано (дори и да знае че е пак gcc то не знае с какви опции и оптимизации) - може да е друг компилтор напр. icc, msvc, asm или даже аз да съм си го набичил бинарен код и няма как да очаква че моя бинарен код ще му разшири правилно параметъра - затова обик. това разширяване се прави преди извикването на функцията защото след това не се знае как.
напр. 8 към 16 бита че по лесно да речем мойта асемблер функция получи 0xFF как ще знае до какво да го разшири правилно 0xFFFF 0x00FF защото не знае какъв е бил смисъла на тези битове преди извикването на функцията т.е. ако е било число със знак то първото е правилно ако е било без знак то второто...
Затова мойто изначално предположение беше че -
1) имаме бъг в gcc - много малко вероятно при положение че препратката която открих е от 1995 досега все щяха да го оправят  :o
2) нямаме бъг в gcc обаче поради някаква причина не match-ва правилната ф-я или библиотека - който се решава много лесно - даже има два начина: или включваме правилния header или поне подсказваме на компилатора с type cast точно коя ф-я и как да match-не
..и аз заложих на второто (че няма бъг в gcc) тъй като първото ми се видя много малко вероятно.

Изводът е - Винаги включвайте правилните хедъри и желателно е явно/експлицитно да преобразувате типовете а не да оставяте компилатора да си развява... и после до го дебъгвате.

Лек ден ви желая и успехи в раследването
П.П. За съжаление нямам време теди дни да разследвам повече и аз...

П.П.П. Дори и модули компилирани с един с същ компилатор може да имат проблеми заради напр. различни опции по време на компилация напр. даже Майкрософт предупреждаватза "модули" компилирани и от двете страни със същия т.е. техния компилатор не се препоръчва да се link-ват когато са компилирани с различни опции напр. едно и също нещо да ползват като напр. STL (string) защото може да го видят различно :-) според зависи напр. дали DLL е компилиран като много нишков или не и дали е с поддръжка на др. библиотеки от майкросфт напр. MSVCRT*.DLL и с какви оптимизации такак че дори и просто нещо като sizeof(string) да връща различен резултат или дори и да е еднакъв то напр. масив от низове да се подравнява различно.

Извинявайте но в момента се боря с Уиндоус програмиране а и... време e да дадем път и повод и на по-млaдите вече да се изяват. Очакваме резултата шошонче  >:D

Последна редакция:
при мен ldd показа това
        linux-vdso.so.1 =>  (0x00007fff7a573000)
        libc.so.6 => /lib64/libc.so.6 (0x00000030a7200000)
        /lib64/ld-linux-x86-64.so.2 (0x00000030a6e00000)

при следните резултати от strace:

no unistd type cast
lseek(3, 18446744073709551606, SEEK_SET) = -1 EINVAL (Invalid argument)

no unistd no type cast
lseek(3, 4294967286, SEEK_SET)          = 4294967286

unistd no type cast
lseek(3, 18446744073709551606, SEEK_SET) = -1 EINVAL (Invalid argument)

unistd type cast
lseek(3, 18446744073709551606, SEEK_SET) = -1 EINVAL (Invalid argument)

също забелязах и това че винаги присъства т.е. O_LARGEFILE възможно да и ма пръст в цялата работа...
fcntl(4, F_GETFL)                       = 0x8002 (flags O_RDWR|O_LARGEFILE)
« Последна редакция: Aug 30, 2012, 20:38 от remotex »
Активен

kifavi8024

  • Новаци
  • *
  • Публикации: 0
    • Профил
Re: Малък въпрос за lseek()
« Отговор #18 -: Aug 30, 2012, 21:01 »
А добре де, гледам че има lseek64(). Интересно ми е при нея дали поведението ще е еквивалентно?
Да не се окаже, че когато го няма header-a, тогава да вика lseek64() или нещо подобно. Но определено има проблем и с linker-a.

На мен ми е интересно от къде ти хрумна пък да пробваш без header :D
Активен

gat3way

  • Напреднали
  • *****
  • Публикации: 6050
  • Relentless troll
    • Профил
    • WWW
Re: Малък въпрос за lseek()
« Отговор #19 -: Aug 30, 2012, 21:40 »
Цитат
Не смятам че оптимизацията на gat3way е валидна в случай като нашия когато се вика код от друг модул /библиотечна функция/ по принцип такива оптимизации са възможни само в/върху един и същи т.нар. translation unit или 1 файл или хайде проект да го наречем - само когато и извикващата и извикваната функция се компилират от същия компилатор и той знае какво да очаква и от двете страни. В случая с викането на библиотечна ф-я или изобщо код от друг translation unit компилатора няма как да знае онова чудо(вище) отсреща как е компилирано (дори и да знае че е пак gcc то не знае с какви опции и оптимизации) - може да е друг компилтор напр. icc, msvc, asm или даже аз да съм си го набичил бинарен код и няма как да очаква че моя бинарен код ще му разшири правилно параметъра - затова обик. това разширяване се прави преди извикването на функцията защото след това не се знае как.

Ммммне, знае как. Има ABI което специфицира как се викат функции, как се разполагат аргументите, в кои регистри или в стека, съответно върнатата стойност от функцията къде и как се пази, дали в регистър, дали в стека. При x86_64 може да се каже че е доста стандартизирано, при x86 може да има разновидности, но на практика дори там под линукс нещата стават предимно по един начин. Това е що се отнася до линукс. Така че такива оптимизации са напълно възможни между различни object файлове, както и в случая когато ползваш външна библиотека.
Активен

"Knowledge is power" - France is Bacon

remotex

  • Напреднали
  • *****
  • Публикации: 344
    • Профил
Re: Малък въпрос за lseek()
« Отговор #20 -: Aug 30, 2012, 21:47 »
Хехех как-как ясно е как... учебникарските примери почти винаги забравят по някой и друг хедър (па и не само те)
После се оправадат че било нарочно оставено за "Упражнение" на четящите...
та човекът по едно време се усетил че нещо липсва и явно е наблюдателен та... ще стане програмист от него щом е забелязал разликата  8)

gat3way Без да съм ескперт по ABI не бих се съгласил че напр. f(32, 32, 32) ще match-не f(32, 64, 32) нарочно не пиша int а кое колко бита заема щото нали съкращението означава бинарен интерфейс т.е. докато подаваш 32,32,32 ще върви но на 32,64,32 или др. различно няма и .. те затова обик сменят API а пък ABI НЕ БАРАТ
Инак... разгледай следната учебникарска постановка напр. с т.нар function overloading
f(int32_t, int32_t, int32_t)
f(int32_t, int64_t, int32_t)
f(-10, -10, -10) - коя функция ще извика според теб - ще извика втората на куково лято - каквото и ABI да има - докато вижда и първата без type cast няма как да извика другата.

http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8a.doc%2Flanguage%2Fref%2Fcplr312.htm

Та затова и според мен везните наклониха повече към линкера

Аз пък все си мисля че преобразувнаето ако се налага такова по Стандарт трябва да става от викащата страна - мисля че правилото беше първо се разширява до съответния по-голям тип със знак и след това се взима без знак ако трябва т.е. 0xFF -> 0xFFFF (-1 или 65535 зависи от другата страна дали е със знак или без параметъра) което е добре дошло ако имаме предвид -1, но ако сме подали 255(а излиза 65535) жална му майка - озадачава ме че нашият случай е точно обратният

П.П. Уточнявам че скоро не съм барал линукс - само джамове и пр. та не съм много навътре как стоят нещата на ниво kernel, ABI и т.п. - карам по стари спомени

П.П.П. Може би аз намесвам повече с++ признавам си. Може би има ABI на ниво kernel но напр. ако си пиша и програмата аз и библиотеката (статична или не) аз никой не може да ме задължи да ползвам каквото и да е - дали в стека или в регистри - особено па ако и пиша на асемблер :-) но да не се отклоняваме - практически пример - библиотеката подава/очаква std::string обаче не експортва статичен такъв или дефиницията тогава какво правим ако приложението е компилирано с различни опции или пък с друга версия на STL т.е. разминават им се вижданията за класа std::string (c++ only) Ще ти кажа какво става - едното подава обект което другото не знае какво да прави, но най-лошото е че си мисли че знае. Стига му и един байт разлика отместване и итератора почва да итерира каквото си иска. Хедъра е правилен т.е. същият и при двете компилации - просто вижданията на компилатор, линкер, опции на предните две и т.н. са различни.
« Последна редакция: Aug 30, 2012, 22:15 от remotex »
Активен

gat3way

  • Напреднали
  • *****
  • Публикации: 6050
  • Relentless troll
    • Профил
    • WWW
Re: Малък въпрос за lseek()
« Отговор #21 -: Aug 30, 2012, 22:02 »
Това е въпрос на прототип на функцията, не на calling конвенцията. Независимо дали ще предаваш 32-битова или 64-битова стойност, аргумента се предава в 64-битов регистър. Дали това е ефективно или не е, е отделен въпрос, но е факт че това работи много добре без много значение какъв тип са аргументите.

Това което искам да кажа е че ти на практика без значение дали го осъзнаваш, винаги подаваш f(64,64,64), без значение дали прототипа на функцията не е f(32,32,64) примерно. Това че функцията очаква 32-битова стойност или че ти подаваш 32-битова стойност, по никакъв начин не променя начина по който викаш функцията - няма специален случай описващ 32-битовите и друг специален случай описващ 64-битовите аргументи, това би било ужасно сложно.

Активен

"Knowledge is power" - France is Bacon

remotex

  • Напреднали
  • *****
  • Публикации: 344
    • Профил
Re: Малък въпрос за lseek()
« Отговор #22 -: Aug 30, 2012, 22:07 »
По мои спомени при 64 бита могат да се подават параметри в регистрите макс. до 4 параметъра/регистъра ако функцията има повече задължително стек.
Аз говорех по принцип - за конкретната функция - може да се ползва подаване чрез регистрите но може и да не се - зависи от опциите при компилиране - предполагам повечето компилатори ще опитмизират и ще опитат да ползват регистри но няма начин и да няма начин изрично да се укаже с опция при компилация дори и един парам да има - През СТЕКА и толкоз.

Но всичко това няма отношение по темата ако извикващата страна е разширила типовете правилно - защото извикваната функция не знае нищо - тя си мисли че подаденто отговаря на т.нар. ABI и ползва напр. само еди коя си половина от 1 и 3 регистър пък регистър 2 целия т.е. 64 бита но не и е работа да знае т.е. тя даже не знае при ст-т в регистъра 2 напр. 0000FFF6 това FFF6 ли е та да го разпъна FFFF FFF6 или е вече разширено и си е 0000FFF6
т.е. ABI се дава за да се спазва от викащата страна - откъм виканата страна - там разработчиците си знаят нали те го правят този ABI :-) (А да верно и те също си го спазват)
т.е. ако ABI нещо не отговаря или не се спазва откъм библиотеката която гое декларирала... ами обикновено скоро тая библиотека излиза с нов ABI  ^-^ и всички дето я ползваме или оставаме въразни към старата версия или си оправяме софтуера да работи с новата библиотека/ABI
така де откъм тяхна страна това не е бъг (неспaзването на собствен ABI), докато ако е от наша си е - колкото и витиевато да звучи си е така. Реакциите обик. са:  - разработчик на либ/ABI : А-а ще го сменяме скоро и пак ще отговаря докато отношението спрямо разработчик потребител е - не ползвате правилно ABI оправете си кода  - т.е. ако е при нас (ползващите либа) е бъг, а ако е при тях (баш дивелъпърите) не е - [_]3 за новите features дет се вика

П.П. gat3way да приключим спора: Доколкото разбирам ти твърдиш че при ABI и ф-я с парам. 32, 64, 32 компилатора може да подаде и 32 битова ст-т на втория парам а виканата фунцкия от либ компилиран с незнаен компилатор (може и да не е компилиран ами напр. аз бичим машинен код направо) ще знае как да го разшири правилно и всичко това щото било имало ABI. Аз изхождам от тезата че подаден числов литерал -10 в сл. от викащата страна виканата няма как да знае как да го разшири - ок виканата страна ще знае да очаква не 32 ами 64, може дори да знае (макар че тук навлизаме в сферата на ненаучната фантастика) че "аз чекам 64 бит ама ми е подаден 32 бит парам ама през регистър който винаги е 64 бит та не мога да съм сигурен щото не знам колегата 'различен компилатор' как е решил да го подаде, но да кажем че знае че в тия подадени му 64 бита само едните 32 бита са валидни т.е. ще требе импилицитно разширяване до 64 бит - как? като не знаем изначалното -10 ли е било или FFFF FFF6; та да си остане -10 -> -10 и FFFF FFF6 -> 0000 0000 FFFF FFF6;
В повечето случаи ще стане (както е по стандарт) FFFF FFFF FFFF FFF6 т.е. първо се разширява към по-големия тип със знак после се каства като без знак (ако се налага)

Спор няма че нашия конкретен случай е различен не става FFFF FFFF FFFF FFF6 ами е точно орязаното FFFF FFF6
Инак гледам и двамата клоним към това че не требе да е 32 бита нещо там тоя средния парам. и че не трябва да е без знак т.е. спор няма :-)

Мир!
« Последна редакция: Aug 30, 2012, 22:39 от remotex »
Активен

kifavi8024

  • Новаци
  • *
  • Публикации: 0
    • Профил
Re: Малък въпрос за lseek()
« Отговор #23 -: Aug 30, 2012, 22:08 »
gateway Ема това не е ли случая, когато процесора е х86_64.
Така ли е или още при х86 си ползва >=64 битови регистри (естествено това при процесорите с SSE инструкциите).
Активен

remotex

  • Напреднали
  • *****
  • Публикации: 344
    • Профил
Re: Малък въпрос за lseek()
« Отговор #24 -: Aug 30, 2012, 22:52 »
Значи да обобщя (докато сме още в кратко примирие)
Засега варинатите са
1. бъг в gcc вижда правилната функция lseek (64 бита) но не разширява правилно параметъра
2. бъг gcc (или linker) не вижда правилната функция ами ползва друга с (32 бит) параметър
като последния има и още един 3. бъг в gcc или либа който ако параметъра правилно е 32 битов би трябвало да приеме параметъра като -10 и да върне грешка а не да го ползва все-едно е приблизително 4G и да прави голям sparse file

П.П. Не знам под линукс това O_LARGEFILE може ли да го разшири параметъра на без знак ..мисля че под линукс направо го направиха 64 битов дори и за 32 битовия либ... По мои спомени джамовете по едно време вдигнаха лимита от 2Г само на 4Г та там може и да има и 32 бит signed и unsigned вариант. Въпросът ми е O_LARGEFILE 64 бит парам прави ли го без знак и каква роля играе когато изначално сме 64 бит ОС, либ и пр. защото това показа strace при мен (64 битово ми е всичко)

П.П.П. Изводът е Винаги ползвайте правилните хедъри и конвертирайте типовече явно и.. по-горе съм дал препратки по темата 64 битов код, портване 32 към 64 бита, коне който могат да говорят и пр. - интересни нещица, стига да има време и желание човек да се образова.

И малко встрани от темата - това че пиша под Уидноус не значи че не ползваме сводобен и товорен софтуер.. Само не ме питайте как се портва за Уиндоус 64 бит - повечето проекти с отворен код казват да имаме версия за Уиндоус и тя... обик. е само 32 бита а то в днешно време няма откъде да си купи човек такова желязо и в дейстовтелност е абсолютно не портабъл кода -  да под линукс работи (да не забравяме че модела е различен - затова LLP64/IL32P64 модела) но в действителност не им пука за уиндоус версията (ей тъй само колкото да кажат че имат)
« Последна редакция: Aug 30, 2012, 23:06 от remotex »
Активен

gat3way

  • Напреднали
  • *****
  • Публикации: 6050
  • Relentless troll
    • Профил
    • WWW
Re: Малък въпрос за lseek()
« Отговор #25 -: Aug 30, 2012, 23:04 »
Абе ей! :)

Има само една calling конвенция за линукс, x86_64, която е специфицирана от sysv amd64 abi-то. И параметрите се подават по един и същ начин, компилаторът не може да си решава самоинициативно как да го прави. Първите 6-7 параметъра се предават през регистри (floating point аргументите се предават през SSE регистри), останалите - в стека, резултатът се връща в rax.

Цитат
Аз изхождам от тезата че подаден числов литерал -10 в сл. от викащата страна виканата няма как да знае как да го разшири - ок виканата страна ще знае да очаква не 32 ами 64, може дори да знае (макар че тук навлизаме в сферата на ненаучната фантастика) че "аз чекам 64 бит ама ми е подаден 32 бит парам ама през регистър който винаги е 64 бит та не мога да съм сигурен щото не знам колегата 'различен компилатор' как е решил да го подаде,

Това е точно така - не знае. Единственият начин програмата ти да знае какво и как да подаде е да има правилния прототип на функцията. Ако това не е налице - примерно ще викне lseek с offset от 4 милиарда вместо -10.

Цитат
64 бита само едните 32 бита са валидни т.е. ще требе импилицитно разширяване до 64 бит - как? като не знаем изначалното -10 ли е било или FFFF FFF6; та да си остане -10 -> -10 и FFFF FFF6 -> 0000 0000 FFFF FFF6;
В повечето случаи ще стане (както е по стандарт) FFFF FFFF FFFF FFF6 т.е. първо се разширява към по-големия тип със знак после се каства като без знак (ако се налага)

Никой имплицитно няма нищо да разширява. В смисъл хубаво е човек да вярва че някой се грижи за него, обаче реалността е сурова. Какво ще му подадеш е едно, какво ще се интерпретира е друго. Няма наготово някакъв механизъм който да прави това по-безопасно. Като му подадеш 32-битовата стойност 0xfffffff6, а той е очаквал 64-битова стойност, ще го интерпретира като 0x00000000fffffff6 и естествено ще се наака, мисля че това се видя вече.

Обаче честно казано не знам за какво спорим :)
Активен

"Knowledge is power" - France is Bacon

remotex

  • Напреднали
  • *****
  • Публикации: 344
    • Профил
Re: Малък въпрос за lseek()
« Отговор #26 -: Aug 30, 2012, 23:14 »
На C (и C++ като наследник) има едно нещо наречено the Standard което казва че всяко нещо има тип - когато не е указан явно както е в сл. напр. с литерала -10 (-10L и (off_t)(-10) са друго нещо типа им е указан) то за това -10 се приема че е тип int т.е. цяло число със знак и когато имаш
int64_t t = -10
или
fun(int64_t param) -> fun (-10);
то в тези случаи -10 което е int се разширява имплицитно първо до по-големия тип със знак и после каст до без знак ПРЕДИ да се присвои или извика функцията.

За да не стане това аз виждам следните възможности: или gcc вижда неправилната функция или вижда правилната но поради бъг не прави правилно имплицитното конвертиране - понеже поне от публикувания асембелерен код се видя че още преди извикването на ф-ята параметъра не е очаквания.

Затова й предположих че не свързва кода с правилната функция от либ-а. т.е. match-ва нещо дурго ПРЕДИ правилното нещо - защо тогава пак БЕЗ unistd.h но с (off_t)(-10) работи правилно (нямам време сега да пробвам и с -10L)

Па може и да сме нацелили бъг няма само джавата да води класациите я :-)
http://www.h-online.com/open/news/item/Java-0Day-Turn-off-Java-applets-now-1678618.html
« Последна редакция: Aug 30, 2012, 23:24 от remotex »
Активен

gat3way

  • Напреднали
  • *****
  • Публикации: 6050
  • Relentless troll
    • Профил
    • WWW
Re: Малък въпрос за lseek()
« Отговор #27 -: Aug 31, 2012, 00:00 »
Мисля, че gcc не е виновен - просто прототипа на функцията е "грешен" (не отговарящ на lseek() в glibc) поради някаква причина когато не се include-не unistd.h.  В смисъл сигурно ще е вълнуващо преживяване да се проследи какво се случва в системните хедъри и свинщината от препроцесорни директиви там, но нямам много мотивация да го правя в момента :)

Това което мога да кажа със сигурност е че това не се случва на ubuntu 12.04 (в момента нямам достъп до железарията в София, за да проверя как се държи с други инсталации).
Активен

"Knowledge is power" - France is Bacon

bvbfan

  • Напреднали
  • *****
  • Публикации: 1056
  • Distribution: KaOS
  • Window Manager: Plasma 5
    • Профил
Re: Малък въпрос за lseek()
« Отговор #28 -: Aug 31, 2012, 13:26 »
Няма никакъв проблем в компилатора и функциите наистина са 2 lseek и lseek64, инклудването на unistd.h е абсолютно необходимо:
Код
GeSHi (C):
  1. #ifndef __USE_FILE_OFFSET64
  2. extern __off_t lseek (int __fd, __off_t __offset, int __whence) __THROW;
  3. #else
  4. # ifdef __REDIRECT_NTH
  5. extern __off64_t __REDIRECT_NTH (lseek,
  6.                                (int __fd, __off64_t __offset, int __whence),
  7.                                 lseek64);
  8. # else
  9. #  define lseek lseek64
  10. # endif
  11. #endif
  12. #ifdef __USE_LARGEFILE64
  13. extern __off64_t lseek64 (int __fd, __off64_t __offset, int __whence)
  14.      __THROW;
  15. #endif
иначе ще се викне 32 битовата версия. Функциите с 2 прототипа (без и с 64 отзад) да ви заблудят много сериозно  ;)
Ето и файлът от glibc  2.16.0 -> http://fossies.org/dox/glibc-2.16.0/posix_2unistd_8h_source.html
Активен

kifavi8024

  • Новаци
  • *
  • Публикации: 0
    • Профил
Re: Малък въпрос за lseek()
« Отговор #29 -: Aug 31, 2012, 14:45 »
Хахахаха знаех си. :D
Еми поуката деца е:
Да внимавате какво и къде има, защото иначе стават подобни карамболи :)
Активен