Ошибка в вычислениях адресов у GCC ?

Jan 27, 2005 Last reply: 21 years ago 566 Replies

Fri Jan 28 2005 07:53, Harry Zhurov wrote to Leha Bishletov:

HZ> int Array[N];

HZ> Array[3] = 5;

HZ> но если написать:

HZ> int* p;

Забыл присвоить начальное значение. p = Array;

HZ> p[3] = 5;

HZ> то получишь, afair, неопределенное поведение.

Hет. Это по определению полностью эквивалентно Array[3] = 5;

iso9899-c99.pdf ...

6.5.2.1 Array subscripting ... The definition of the subscript operator [] is that E1[E2] is identical to (*((E1)+(E2))). ...

WBR, Yuriy

Fri Jan 28 2005 07:53, Harry Zhurov wrote to Yuriy K:

GZ>>>> "по стандарту" результат таких выражений определен, если сравниваются GZ>>>> или вычитаются адреса элементов одного массива между собой.

HZ>>> А что, если

HZ>>> extern int i1; HZ>>> extern int i2;

HZ>>> ... HZ>>> ip1 = &i1; HZ>>> ip2 = &i2;

HZ>>> то ip1 - ip2 не определено, что-ли?

YK>> Hе определено.

YK>> iso9899-c99.pdf: YK>> ... YK>> 6.5.6 Additive operators YK>> ... YK>> 9 When two pointers are subtracted, both shall point to elements of the YK>> same array object, or one past the last element of the array object; YK>> the result is the difference of the subscripts of the two array YK>> elements. ...

HZ> И где тут английским по белому написано, что _не_ _определено_? HZ> Где слово undefined?

iso9899-c99.pdf: ... J.2 Undefined behavior

1 The behavior is undefined in the following circumstances: ...

- Pointers that do not point into, or just beyond, the same array object are subtracted (6.5.6). ...

WBR, Yuriy

27-Jan-05 14:15 Harry Zhurov wrote to Genadi Zawidowski:

HZ> А что, если HZ> extern int i1; HZ> extern int i2; HZ> ... HZ> ip1 = &i1; HZ> ip2 = &i2;

HZ> то ip1 - ip2 не определено, что-ли? Не определено.

HZ> Вполне определено - конкретное число HZ> получится. Модуль этого числа указывает, сколько интов помещается в HZ> кусок HZ> памяти между адресуемыми переменными. Другое дело, что какого-то практического HZ> смысла в этом не видно. Про некратность разницы адресов размеру int уже сказали. На том же AVR между этими двумя интами влезет какой-то char и приплыли.

Вариант два - адреса far на архитектуре x86, состоят из сегмента и смещения. Ну именно на 8086 ещё можно подсуетиться и посчитать, а в защищённом режиме? Когда там сегменты - это не адреса?

wbr,

Fri, 28 Jan 2005 08:16:58 +0300 Yuriy K wrote to Harry Zhurov:

HZ>> int Array[N];

HZ>> Array[3] = 5;

HZ>> но если написать:

HZ>> int* p;

YK> Забыл присвоить начальное значение. YK> p = Array;

Ничего я тут не забыл! Цель этого примера - продемонстрировать разницу между массивом и указателем! Только и всего. Или ты тоже будешь утверждать, что массив и указатель есть одно и то же?

HZ>> p[3] = 5;

HZ>> то получишь, afair, неопределенное поведение.

YK> Hет. Это по определению полностью эквивалентно YK> Array[3] = 5;

Блин, ты сообщение-то внимательно читал? Не надо выдергивать из контекста! Контекст был в первом случае "int Array[N]", во втором "int* p". И речь шла не про синтаксис адресации, а про то, что во втором случае значение прописывается по неопределенному адресу - вот это уж точно будет неопределенное поведение!

Fri, 28 Jan 2005 05:34:39 +0000 (UTC) Oleksandr Redchuk wrote to "Harry Zhurov" snipped-for-privacy@online.nsk.su>:

[...]

HZ>> то ip1 - ip2 не определено, что-ли? OR> Не определено.

HZ>> Вполне определено - конкретное число HZ>> получится. Модуль этого числа указывает, сколько интов помещается в HZ>> кусок HZ>> памяти между адресуемыми переменными. Другое дело, что какого-то HZ>> практического смысла в этом не видно. OR> Про некратность разницы адресов размеру int уже сказали. На том же AVR OR> между этими двумя интами влезет какой-то char и приплыли.

А если на том же AVR char* ip1; char* ip2;, то как?

OR> Вариант два - адреса far на архитектуре x86, состоят из сегмента и OR> смещения. Ну именно на 8086 ещё можно подсуетиться и посчитать, а OR> в защищённом режиме? Когда там сегменты - это не адреса?

Если на одной платформе нельзя предсказать, а на другой можно, то это как называется? Неопределенное - это когда ни на одной платформе нельзя предсказать? Или хотя бы на одной? А зависящее от реализации - это когда зная конкретную платформу, можно предсказать? Или надо, чтобы это можно было предсказать для любой конкретной платформы, а если есть хотя бы одна, для которой нельзя, то тогда это undefined behaviour, а не implementation-defined? Где истина?

И потом, одно дело неопределенное поведение [программы], другое - неопределенное значение результата выражения. Это, мне кажется, несколько разные вещи.

Fri Jan 28 2005 10:58, Harry Zhurov wrote to Yuriy K: HZ> [...]

HZ>>> И где тут английским по белому написано, что _не_ _определено_? HZ>>> Где слово undefined?

YK>> iso9899-c99.pdf: YK>> ... YK>> J.2 Undefined behavior

YK>> 1 The behavior is undefined in the following circumstances: YK>> ... YK>> - Pointers that do not point into, or just beyond, the same array object YK>> are subtracted (6.5.6). YK>> ...

HZ> Hе можешь пояснить на примере, к чему это приводит? Какой механизм HZ> прихода к неопределенному поведению при выполнении выражения "int a = pi1 HZ> - pi2;"? Hапример, на AVR

Еще раз. В _стандарте_ написано, что поведение _не_определено. Механизм, причины и результаты не имеют ни малейшего значения.

WBR, Yuriy

Fri Jan 28 2005 10:58, Harry Zhurov wrote to Oleksandr Redchuk:

HZ>>> то ip1 - ip2 не определено, что-ли? OR>> Hе определено.

HZ>>> Вполне определено - конкретное число HZ>>> получится. Модуль этого числа указывает, сколько интов помещается в HZ>>> кусок HZ>>> памяти между адресуемыми переменными. Другое дело, что какого-то HZ>>> практического смысла в этом не видно. OR>> Про некратность разницы адресов размеру int уже сказали. Hа том же AVR OR>> между этими двумя интами влезет какой-то char и приплыли.

HZ> А если на том же AVR char* ip1; char* ip2;, то как?

J.2.

OR>> Вариант два - адреса far на архитектуре x86, состоят из сегмента и OR>> смещения. Hу именно на 8086 ещё можно подсуетиться и посчитать, а OR>> в защищённом режиме? Когда там сегменты - это не адреса?

HZ> Если на одной платформе нельзя предсказать, а на другой можно, то это HZ> как называется? Hеопределенное - это когда ни на одной платформе нельзя HZ> предсказать? Или хотя бы на одной? А зависящее от реализации - это когда HZ> зная конкретную платформу, можно предсказать? Или надо, чтобы это можно HZ> было предсказать для любой конкретной платформы, а если есть хотя бы HZ> одна, для которой нельзя, то тогда это undefined behaviour, а не HZ> implementation-defined? Где истина?

iso9899-c99.pdf

3.4.3 1 undefined behavior

behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this International Standard imposes no requirements

2 NOTE Possible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message).

3 EXAMPLE An example of undefined behavior is the behavior on integer overflow.

HZ> И потом, одно дело неопределенное поведение [программы], другое - HZ> неопределенное значение результата выражения. Это, мне кажется, несколько HZ> разные вещи.

Все расписано. Тебе iso9899-c99.pdf выслать?

WBR, Yuriy

2005-01-28, Harry Zhurov snipped-for-privacy@online.nsk.su> пишет:

Нет. Какие это средства в приличных компиляторах? Очередное нестандартное расширение? В gcc это достигается неспециальным расширением.

Описанное выше - не хак, а совершенно законный механизм, разве что отсутсвующий в языке Си.

А вот этого - никто не обещал.

Секции - гораздо более переносимый и гарантированный от изменений механизм, чем размещение стека.

2005-01-27, Yuriy K snipped-for-privacy@taekwondo.co.nz> пишет:

Программист. Тот же, что пишет программу. Это его святая обязанность.

RTFM ld. Он "однопроходный" без специальных ключей. Фича.

Ты не понял? Я говорил как раз о секциях. Но в стандарт языка Си этот механизм не входит, всегда - только нестандартными расширениями.

Как узнать адреса начала и конца секции средствами языка Си? Я описал способ.

Fri Jan 28 2005 14:49, Dmitry Fedorov wrote to Yuriy K:

DF> Программист. Тот же, что пишет программу. Это его святая обязанность.

1) Hаличие makefile не обязательно. 2) Может генерироваться средствами среды. 3) Где в программе написаны указания программисту, в каком порядке линковать файлы.

DF> RTFM ld. Он "однопроходный" без специальных ключей. Фича.

Дык. Глюкодром и ламерство.

"Стандартный" не в смысле "описанный в стандарте", а в смысле "наиболее удобный и правильный".

DF> Ты не понял? Я говорил как раз о секциях. DF> Hо в стандарт языка Си этот механизм не входит, всегда - только DF> нестандартными расширениями.

Makefile в стандарт языка не входит. Особенности линкера и последовательность линковки в стандарт языка не входит. Память не обязана быть линейной и непрерывной. Управление размещением памяти в стандарт языка не входит.

Поэтому

DF> Как узнать адреса начала и конца секции средствами языка Си?

Hикак.

DF> Я описал способ.

Hет. Ты закладываешься на последовательность линковки, не описываемую средствами языка С.

WBR, Yuriy

Fri, 28 Jan 2005 11:49:18 +0000 (UTC) Dmitry Fedorov wrote to Harry Zhurov:

DF>>> Для глобальных символов смысл есть. Пару глобальных символов размещают в DF>>> одной секции в первом и последнем объектных файлах и получают в DF>>> программе возможность определить размер секции и что такой-то объект DF>>> входит в эту секцию. При этом - никакого ассемблера (с GNU расширениями).

DF> Нет. Какие это средства в приличных компиляторах? DF> Очередное нестандартное расширение?

Да. А как ты хотел? Требования по конкретному размещению объектов со стороны пользователя сами по себе нестандартны, поэтому и средства для этого нестандартны. Что-то мне не кажется, что реализация нестандартного требования путем использования стандартных средств нестандартным способом лучше, чем специальное нестандартное средство. А геморроя больше.

[...]

DF> А вот этого - никто не обещал.

Т.е. может быть "дырявый" стек? Например?

DF> Секции - гораздо более переносимый и гарантированный от изменений механизм, DF> чем размещение стека.

С чего это? Насколько я ничего не понимаю, и то, и другое не входят в понятия языка.

Hello, Harry Zhurov !

Его в аппаратном виде может вовсе не быть.

С уважением, Дима Орлов.

2005-01-28, Yuriy K snipped-for-privacy@taekwondo.co.nz> пишет:

Хоть какое средство автоматизации сборки необходимо.

Может. Но это ничего не меняет - изволь иметь средства указания среде.

Не программисту дают указания, а программист дает указания. Makefile или его аналог - часть программы.

Цитата:

Мало ли чего в стандарт языка не входит и достигается внешними средствами.

А секция обязана быть линейной и непрерывной?

Так опиши свой способ, в рамках языка Си.

2005-01-28, Harry Zhurov snipped-for-privacy@online.nsk.su> пишет:

Те средства - тоже нестандартны.

Неважно. Разность адресов статических символов имеет иногда какой-то смысл. Разность адресов автоматических переменных - нет.

Не входит. Но "гораздо более переносимы".

Sat Jan 29 2005 14:48, Dmitry Fedorov wrote to Yuriy K:

IDE, например.

formatting link
- где в IDE описана последовательность линковки?

DF> Hе программисту дают указания, а программист дает указания. DF> Makefile или его аналог - часть программы.

Программист уволился, наняли другого. Откуда он знает требуемую последовательность линковки?

Как опишешь, так и будет.

Hе существует. Читайте стандарты.

P.S. Результаты работы "программистов" пишущих программы, зависящие от последовательности линковки, мне уже приходилость переделывать...

WBR, Yuriy

2005-01-29, Yuriy K snipped-for-privacy@taekwondo.co.nz> пишет:

У нас с тобой разные понятия о среде.

Это проблема твоей IDE.

Последовательность записана в Makefile. Пользователю мakefile знать об этом не обязательно - оно работает (собирается) и без этого знания.

Я пользуюсь стандартными секциями, определеннымы в скриптах линкера для данной платформы. Они непрерывны. Или я определяю секции линейными и непрерывными. Как хочу.

Ф-фух! Я в курсе, что в языке Си этих средств нет. Значит, используются внешние средства. В данном случае это линкер и пара файлов на ассемблере, вместо которых можно использовать расширение языка, позволяющее помещать объект в заданную секцию.

Что неудивительно, для пользующихся IDE.

Sat Jan 29 2005 18:09, Dmitry Fedorov wrote to Yuriy K:

1) Минимум 90% программистов про makefile не слышали.

2) Программистов бывает больше одного.

DF> У нас с тобой разные понятия о среде.

Безусловно.

DF> Это проблема твоей IDE.

Конструктивного ответа не будет?

DF> Последовательность записана в Makefile. DF> Пользователю мakefile знать об этом не обязательно - оно работает DF> (собирается) и без этого знания.

Добавили/удалили пару файлов. Что делать? Где описано, как изменять makefile? Откуда об этом узнает новый человек?

Hе обязательно. Платформы бывают разные. Память бывает с дырками, может состоять из нескольких кусков.

DF> Или я определяю секции линейными и непрерывными. Как хочу.

Придется вводить много разных секций для кода. Исключительно неудобно.

Тогда зачем спрашиваешь?

------------- Пока проект маленький и разрабатывается одним незаменимым человеком можно писать что угодно и как угодно, лишь бы человек был хороший. :)

Когда проект побольше, рограммистов несколько, они приходят и уходят, все эти левые зависимости тут же вылезают боком.

WBR, Yuriy

Hello, Dmitry!

Пят Янв 28 2005, Dmitry Fedorov писал к Yuriy K по поводу "Re: Ошибка в вычислениях адресов у GCC ?." >> Кто создает makefile? DF> Программист. Тот же, что пишет программу. Это его святая обязанность. Я тоже так думал, пока не увидел makefile размером в 2.1 мегабайта. После детального просмотра выяснилось, что 99.9% этого файла было генерированно каким-то скриптом который прошелся по исходнику ;) Весело бы быдо посмотреть на программиста который подобное писал ручками.

WBR! Maxim Polyanskiy.

Sat Jan 29 2005 23:20, Maxim Polyanskiy wrote to Dmitry Fedorov:

MP> Я тоже так думал, пока не увидел makefile размером в 2.1 мегабайта. После MP> детального просмотра выяснилось, что 99.9% этого файла было генерированно MP> каким-то скриптом который прошелся по исходнику

Есть такой весьма популярный Cosmic C, так вот в нем IDE автоматически создает bat-файл, который запускает компилер, линкер и все прочее с нужными опциями. Вот до чего доходит нелюбовь людей к make из-за его дебильного синтаксиса.

VLV

"Быть честным - лучший способ оставаться бедным" (c) Hаполеон Бонапарт

Sat, 29 Jan 2005 18:24:52 +0300 Yuriy K wrote to Dmitry Fedorov:

DF>>>>>> Программист. Тот же, что пишет программу. Это его святая

YK> 1) Минимум 90% программистов про makefile не слышали.

Это, извини, чушь! Даже в этой эхе, где не программисты собрались, большинство слышало про makefile и знает, что это такое - эта техника сборки уже неоднократно обсуждалась за последние несколько лет. А если пойти в программерскую эху, то там про makefile могут не знать только полные новички.

Вот если для тебя это откровение, то не надо на других прикладывать свой опыт.

YK> 2) Программистов бывает больше одного.

И что? Похоже, что в твоем окружении собрались программисты из п. 1).

DF>>>> Хоть какое средство автоматизации сборки необходимо.

Приличные IDE умеют генерить makefile для сборки с помощью make (кому это удобно).

DF>>>> Может. Hо это ничего не меняет - изволь иметь средства указания

DF>> Это проблема твоей IDE.

YK> Конструктивного ответа не будет?

Я тоже не пользуюсь IDE (хоть IAR, хоть CCS), ибо ацтой! А пользуюсь именно make (и хорошим программерским редактором). А IDE годится только в роли отладчика (исключительно потому, что отладчик в нее встроен).

DF>>>> Hе программисту дают указания, а программист дает указания. DF>>>> Makefile или его аналог - часть программы.

Если этот другой не в состоянии разобраться с makefile, который собирает проект, то с собственно программой ему будет разобраться вряд ли возможно, т.к. сама программа, как правило, гораздо сложнее скрипта сборки.

DF>> Последовательность записана в Makefile. DF>> Пользователю мakefile знать об этом не обязательно - оно работает DF>> (собирается) и без этого знания.

YK> Добавили/удалили пару файлов. Что делать? Где описано, как изменять YK> makefile? Откуда об этом узнает новый человек?

make надо уметь пользоваться. Как и уметь пользоваться IDE. Почему-то у тебя не вызывает вопроса, как этот другой чел будет разбираться с IDE, ее окошками, опциями, установками... А вдруг не разберется?!..

А что значит "линейной"? Память - это не функция из математики.

[...]

YK> Hе обязательно. Платформы бывают разные. Память бывает с дырками, YK> может состоять из нескольких кусков.

И что мешает целостный кусок затолкать в секцию? Или разбить на несколько секций? Каждая такая секция будет непрерывной.

DF>> Или я определяю секции линейными и непрерывными. Как хочу.

YK> Придется вводить много разных секций для кода. Исключительно неудобно.

Нормальный, широкоиспользуемый, где надо, подход. Если он не нужен тебе на AVR или другом МК, то не надо обобщать - есть платформы, где это необходимо и удобно.

[...]

YK> ------------- YK> Пока проект маленький и разрабатывается одним незаменимым человеком можно YK> писать что угодно и как угодно, лишь бы человек был хороший. :)

YK> Когда проект побольше, рограммистов несколько, они приходят и уходят, YK> все эти левые зависимости тут же вылезают боком.

Большие, сложные проекты всегда сложнее маленьких и простых. Коллективная разработка обычно сложнее индивидуальной, т.к. помимо технических вопросов вылезают еще и организационные, которые не поддаются автоматизации. Тут ты Америки не открыл. Но к IDE или make все это имеет весьма опосредованное отношение. И единственный способ держать процесс разработки под контролем - это создание и поддержание комплекса _организационных_ мер! Сюда могут входить перечень стилей кодирования (оформление исходников, правила именования и т.д.), правила документирования как программ, так и рабочего окружения и т.д. И самое главное - грамотный подбор кадров, т.к. "Кадры решают все!" (с) угадай чей.

И если уж сравнивать тут IDE и make, то make имеет явное преимущество, т.к. позволяет полную гибкость - как хочешь, так и организуешь. В отличие от IDE, где ты находишься в рамках и никуда за эти рамки не выйдешь.

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required