Автор | Сообщение |
|
| |
Пост N: 71
Зарегистрирован: 29.07.05
|
|
Отправлено: 25.02.10 15:39. Заголовок: Засада в OemToAnsi
Давно написанная и отлично работающая OemToAnsi понадобилась в другом проекте. я её выделил в отдельный PRG файл, откомпилировал, добавил в свою библиотеку - всё работает. НО случайно обнаружил "красный эффект" - портится ПАРАМЕТР! т.е. Funcion OemToAnsi( cOem ) Local cAnsi := cOem // перекодировка cAnsi, сюда запостить не получится - там одновременно и DOS и Win кодировки ........ Return cAnsi выполнятся cOem := 'Тест' cAnsi := OemToAnsi( cOem ) в результате cOem == cAnsi в старом проекте (где функция не из библиотеки ) этого не происходит. не могу понять - где засада
|
|
|
Ответов - 16
[только новые]
|
|
|
| |
Пост N: 1421
Зарегистрирован: 17.05.05
|
|
Отправлено: 25.02.10 16:19. Заголовок: les Пробуй func o..
les Пробуй func oemtoansi(srt) local j:=len(srt) local i : =1 local ret:="" local asco:="" for i=1 to j asco:=substr(srt,i,1) if asc(asco)<128 ret+=asco elseif asc(asco)>=128 .and. asc(asco)<=175 ret+=chr(asc(asco)+64) elseif asc(asco)>=224 .and. asc(asco)<=239 ret+=chr(asc(asco)+16) else ret+="" endif next RETURN ret
|
|
|
|
| |
Пост N: 72
Зарегистрирован: 29.07.05
|
|
Отправлено: 25.02.10 17:00. Заголовок: Dima пишет: Пробуй ..
Dima пишет: Спасибо конено, у меня тоже есть аналогичная ф-я. вопрос не в методе пекодивки, а почему меняется ПАРАМЕТР. Причём только если прилинковуется из библиотеки. Я просто в шоке
|
|
|
|
| |
Пост N: 70
Зарегистрирован: 01.01.10
|
|
Отправлено: 26.02.10 02:44. Заголовок: Попробуйте изменить ..
Попробуйте изменить оператор RETURN cAnsi на RETURN (cAnsi). Все дело в том, что когда возвращается выражение в скобках то возвращается ЗНАЧЕНИЕ, а в Вашем случае возвращается ССЫЛКА!
|
|
|
|
| |
Пост N: 73
Зарегистрирован: 29.07.05
|
|
Отправлено: 26.02.10 12:57. Заголовок: sergey5703 пишет: П..
sergey5703 пишет: цитата: | Попробуйте изменить оператор RETURN cAnsi на RETURN (cAnsi). Все дело в том, что когда возвращается выражение в скобках то возвращается ЗНАЧЕНИЕ, а в Вашем случае возвращается ССЫЛКА! |
|
Спасибо - помогло Это я знаю, но раньше на эти грабли не наступал. Я в шоке. Каким образом ссылка на локальную для функции переменную cAnsi может повлиять на параметр cOem и переменную вызывающей программы Почему функция входящая в состав проекта и прилинкованая из библиотеки ведут себя по-разному
|
|
|
|
| постоянный участник
|
Пост N: 139
Зарегистрирован: 24.09.05
|
|
Отправлено: 03.03.10 16:16. Заголовок: Ничего подбного, все..
Ничего подбного, все не правы. Никакие скобки тут не при чем. return Ansi и return (Ansi) - это одно и то же, возвращается значение. В этом легко убедиться, сравнив побайтно (fc.exe /b) код, получаемый при компиляции. А переменная вне функции может изменить свое значение только в том случае, если была передана в функцию по ссылке - OemToAnsi(@cOem) Почему переменная всё-таки меняет свое значение, когда функция из библиотеки - легко объяснимо. На клиппере такого эффекта достичь нельзя, как сказано выше. Следовательно, если функция на клиппер и непосредственно в текстах программы - такого эффекта не наблюдается, потому что в первую очередь для разрешения неопределенных ссылок используются объектные модули. А вот когда ты ее помещаешь в библиотеку - линковщик после просмотра OBJ ищет неразрешенные ссылки в библиотеках, в порядке их указания. Скорее всего, в одной из твоих библиотек есть функция точно с таким же именем, которая написана на ассемблере. В этом легко убедиться, сделав листинг всех библиотек - ты найдешь ее. Так же в подтверждение этой теории ты можешь вообще выкинуть свою функцию на клиппере - слинкуется без ошибок. И написана эта ассемблерная функция неправильно. Обычно, при программировании на ассемблере под клиппер необходимо прилагать значительные усилия, чтобы не изменить параметр - выделять память (а вдруг переменная большая (64К) и в данный момент такого куска свободной памяти не будет, что тогда?), копировать туда значение. Поэтому возникает соблазн большой получить ссылку на параметр (про который в руководстве по экстенд систем сказано - менять его НЕЛЬЗЯ) и сделать перекодировку непосредственно там, при этом переменная конечно же портится. Фактически, в твой фрагмент эквивалентен следующему cOem := 'Тест' cAnsi := OemToAnsi( @cOem ) - передача по ссылке поэтому меняются и cAnsi и сама cOem Если тебе важна скорость работы можешь оставить библиотечную ассемблерную функцию, но при этом учитывать ее особенности. Например, если тебе нужно старое значение - можешь создать его копию. Также, ты можешь указать свою библиотеку самой первой и увидишь, что переменная больше не портится, потому что будет работать твоя функция на клиппере. Также ты можешь не менять порядок линковки, но удалить ассемблерную функцию из библиотеки.
|
|
|
|
| |
Пост N: 74
Зарегистрирован: 29.07.05
|
|
Отправлено: 03.03.10 16:44. Заголовок: suv2 пишет: Когда т..
suv2 пишет: цитата: | Ничего подбного, все не правы. Никакие скобки тут не при чем. return Ansi и return (Ansi) - это одно и то же, возвращается значение. |
| Тем неменее после заключения в скобки функция стала работать нормально. suv2 пишет: цитата: | Когда ты ее помещаешь в библиотеку - линковщик ищет неразрешенные ссылки в порядке указания библиотек. Скорее всего в в одной из твоих библиотек есть функция точно с таким же именем, которая написана на ассемблере. В этом легко убедиться, сделав листинг всех библиотек - ты найдешь ее. |
|
Убирал из своей библиотеки и из текста проекта линковщик ищет неразрешенные ссылки, и не находит. suv2 пишет: цитата: | Фактически, в твой фрагмент эквивалентен следующему cOem := 'Тест' cAnsi := OemToAnsi( @cOem ) - передача по ссылке поэтому меняются и cAnsi и сама cOem |
| 1. я передаю не по ссылке 2. в функции есть Local cAnsi := cOem и перекодируется cAnsi а не cOem
|
|
|
|
| постоянный участник
|
Пост N: 140
Зарегистрирован: 24.09.05
|
|
Отправлено: 03.03.10 16:59. Заголовок: les пишет: Убирал и..
les пишет: цитата: | Тем неменее после заключения в скобки функция стала работать нормально |
| После - не в следствии. Давай я не буду гадать, что ты там еще напутал и поменял, когда добавил скобки. Ты мог изменить порядок линковки библиотек, мог еще чего-то поменять, не заметить и так далее. Повторяю - 1) return (ansi) и return ansi - это ОДНО И ТО ЖЕ 2) никогда и ни при каких обстоятельствах на клиппер ты не сможешь изменить параметр внутри функции, если он не передавался по ссылке. Если ты утверждаешь, что 1) и 2) неверно - сделай тестовый пример, полностью самостоятельный, чтобы его мог проверить любой. Библиотека в которой лежит OemToAnsi на клиппер и больше ничего+PRG с тестом, в котором меняется переменная вне функции и показывается разница между return (ansi) и return ansi + BAT с компиляцией и линковкой + скрипты линковки без использования дополнительных библиотек, кроме стандартных. Обычно, когда доходит дело до тестового примера - его сделать не удается. Это и значит, что ты чего-то не замечаешь. les пишет: цитата: | Убирал из своей библиотеки и из текста проекта линковщик ищет неразрешенные ссылки, и не находит. |
| это полностью подтверждает мою теорию les пишет: цитата: | 1. я передаю не по ссылке 2. в функции есть Local cAnsi := cOem и перекодируется cAnsi а не cOem |
| ты невнимательно читаешь. Речь идет о том, что при невольном использовании ассемблерной функции твой фрагмент становится эквивалентен передаче по ссылке
|
|
|
|
| |
Пост N: 75
Зарегистрирован: 29.07.05
|
|
Отправлено: 03.03.10 17:23. Заголовок: suv2 пишет: ты невн..
suv2 пишет: цитата: | ты невнимательно читаешь. Речь идет о том, что при невольном использовании ассемблерной функции твой фрагмент становится эквивалентен передаче по ссылке |
|
suv2 пишет: цитата: | После - не в следствии. Давай я не буду гадать, что ты там еще напутал и поменял, когда добавил скобки. Ты мог изменить порядок линковки библиотек, мог еще чего-то поменять, не заметить и так далее. Повторяю - 1) return (ansi) и return ansi - это ОДНО И ТО ЖЕ 2) никогда и ни при каких обстоятельствах на клиппер ты не сможешь изменить параметр внутри функции, если он не передавался по ссылке. Если ты утверждаешь, что 1) и 2) неверно |
|
Я всегда свято в это верил. А насчёт поменял - так только скобки suv2 пишет: цитата: | ты невнимательно читаешь. Речь идет о том, что при невольном использовании ассемблерной функции твой фрагмент становится эквивалентен передаче по ссылке |
|
та чтобы там не делалось оно делается с cAnsi причём тут cOem?
|
|
|
|
| постоянный участник
|
Пост N: 141
Зарегистрирован: 24.09.05
|
|
Отправлено: 03.03.10 17:26. Заголовок: les пишет: та чтобы..
les пишет: цитата: | та чтобы там не делалось оно делается с cAnsi причём тут cOem? |
| Я же объяснял - если функция на ассемблере - она может поменять что угодно. Даже если ты передавал по значению, а не по ссылке. Это же ассмеблер) Вот это для кого написано было? - "Обычно, при программировании на ассемблере под клиппер необходимо прилагать значительные усилия, чтобы не изменить параметр - выделять память (а вдруг переменная большая (64К) и в данный момент такого куска свободной памяти не будет, что тогда?), копировать туда значение. Поэтому возникает соблазн большой получить ссылку на параметр (про который в руководстве по экстенд систем сказано - менять его НЕЛЬЗЯ) и сделать перекодировку непосредственно там, при этом переменная конечно же портится." Другими словами. Функция на ассемблере может напрямую работать с переданным параметром и это ее личное дело, создавать ли копию этого параметра, чтобы он не изменился или не создавать. Это только в языках высокого уровня автоматически без твоего участия происходит передача по значению и ты думаешь, что это происходит само-собой. Но на самом деле для передачи по значению необходимо прилагать определенные программные усилия, на которых программисты экономят. Для ассемблера возможно всё - можно изменить что угодно, хоть переменную внутри функции, хоть переменную в другой программе, запущенной до текущей, хоть любой произвольный участок памяти. Функция спрашивает у клиппера адрес параметра и меняет его, не соблюдая никаких соглашений по видимости и по передаче параметров. На клиппере ты таких результатов не получишь никогда. Если параметр меняется - значит виноват ассемблер, так может сделать только он. И никакие скобки не при чем.
|
|
|
|
| постоянный участник
|
Пост N: 359
Зарегистрирован: 17.05.05
|
|
Отправлено: 03.03.10 18:53. Заголовок: suv2 пишет: Обычно,..
suv2 пишет: цитата: | Обычно, при программировании на ассемблере под клиппер необходимо прилагать значительные усилия, чтобы не изменить параметр - выделять память (а вдруг переменная большая (64К) |
| В Clipper никакая переменная не может быть больше 64K. Максимальный размер строковой переменной меньше, чем 64K, за счет специального префикса, который выдяется под системные нужды. По крйней мере 14 байтов надо вычесть из 64K.
|
|
|
|
| постоянный участник
|
Пост N: 142
Зарегистрирован: 24.09.05
|
|
Отправлено: 04.03.10 02:45. Заголовок: Григорьев Владимир п..
Григорьев Владимир пишет: цитата: | В Clipper никакая переменная не может быть больше 64K |
| читай внимательно, там не написано "больше 64к", там написано "большая (64к)"
|
|
|
|
|
| |
Пост N: 76
Зарегистрирован: 29.07.05
|
|
Отправлено: 04.03.10 11:54. Заголовок: suv2 пишет: Функция..
suv2 пишет: цитата: | Функция спрашивает у клиппера адрес параметра и меняет его, не соблюдая никаких соглашений по видимости и по передаче параметров. |
|
В моей ф-и OemToAnsi используется ф-я CharRepl() из CT III от CA, и я сомневаюсь что её писал школьник suv2 пишет: цитата: | На клиппере ты таких результатов не получишь никогда. Если параметр меняется - значит виноват ассемблер, так может сделать только он. |
|
Моя ф-я на Clipper 5.2e цитата: | И никакие скобки не при чем. |
|
Не спорю, но тем не менее... мистика Кстати тестовый пример работает как со скобками так и без.
|
|
|
|
| постоянный участник
|
Пост N: 143
Зарегистрирован: 24.09.05
|
|
Отправлено: 04.03.10 13:19. Заголовок: les пишет: Кстати т..
les пишет: цитата: | Кстати тестовый пример работает как со скобками так и без. |
| Всё, тупик. абсолютно бессодержательный ответ. Могу лишь повторить выводы. Никакой порчи переменных на клиппер получить нельзя. Тестового примера нет и НЕ БУДЕТ Переменные у тебя портит другая функция с таким же именем OemToAnsi, написанная похабно. return (Ansi) и return Ansi - это одно и то же, между ними нет НИКАКОЙ разницы
|
|
|
|
| постоянный участник
|
Пост N: 360
Зарегистрирован: 17.05.05
|
|
Отправлено: 04.03.10 16:33. Заголовок: les пишет: В моей ф..
les пишет: цитата: | В моей ф-и OemToAnsi используется ф-я CharRepl() из CT III от CA, и я сомневаюсь что её писал школьник |
| На самом деле функции из этой библиотеки написаны крайне плохо! Как-то был вопрос по поводу одной функции здесь на форуме, и, отвечая на вопрос, я ее восстановил по объектному коду. Могу подтвердить, что та функция написана бездарно и с ошибками. Так что не следует доверять этой библиотеке. Ее код крайне некачественный.
|
|
|
|
| постоянный участник
|
Пост N: 144
Зарегистрирован: 24.09.05
|
|
Отправлено: 04.03.10 17:46. Заголовок: Григорьев Владимир п..
Григорьев Владимир пишет: цитата: | На самом деле функции из этой библиотеки написаны крайне плохо! |
| +1. И сам клиппер написан препохабнейше. обращения к неинициализированным переменным, запутанная логика, излишние усложнения, отсутствие контроля ошибок. но цэ-тулз - это нечто из ряда вон
|
|
|
|
| Администратор
|
Пост N: 1340
Зарегистрирован: 23.05.05
|
|
Отправлено: 10.03.10 12:03. Заголовок: К слову. Пишу сейчас..
К слову. Пишу сейчас на харборе, и получил по лбу граблями, описанными в этой теме. В функции на С не сделал копию Item, и в результате после работы функции параметр изменил значение
|
|
|
|