On-line: гостей 0. Всего: 0 [подробнее..]
АвторСообщение



Пост 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

в старом проекте (где функция не из библиотеки ) этого не происходит.
не могу понять - где засада


Спасибо: 0 
ПрофильЦитата Ответить
Ответов - 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



Спасибо: 0 
ПрофильЦитата Ответить



Пост N: 72
Зарегистрирован: 29.07.05
ссылка на сообщение  Отправлено: 25.02.10 17:00. Заголовок: Dima пишет: Пробуй ..


Dima пишет:

 цитата:
Пробуй

Спасибо конено, у меня тоже есть аналогичная ф-я.
вопрос не в методе пекодивки, а почему меняется ПАРАМЕТР.
Причём только если прилинковуется из библиотеки.
Я просто в шоке

Спасибо: 0 
ПрофильЦитата Ответить





Пост N: 70
Зарегистрирован: 01.01.10
ссылка на сообщение  Отправлено: 26.02.10 02:44. Заголовок: Попробуйте изменить ..


Попробуйте изменить оператор RETURN cAnsi на RETURN (cAnsi). Все дело в том, что когда возвращается выражение в скобках то возвращается ЗНАЧЕНИЕ, а в Вашем случае возвращается ССЫЛКА!


Спасибо: 0 
ПрофильЦитата Ответить



Пост N: 73
Зарегистрирован: 29.07.05
ссылка на сообщение  Отправлено: 26.02.10 12:57. Заголовок: sergey5703 пишет: П..


sergey5703 пишет:

 цитата:
Попробуйте изменить оператор RETURN cAnsi на RETURN (cAnsi). Все дело в том, что когда возвращается выражение в скобках то возвращается ЗНАЧЕНИЕ, а в Вашем случае возвращается ССЫЛКА!

Спасибо - помогло
Это я знаю, но раньше на эти грабли не наступал.
Я в шоке. Каким образом ссылка на локальную для функции переменную cAnsi может повлиять на параметр cOem и переменную вызывающей программы
Почему функция входящая в состав проекта и прилинкованая из библиотеки ведут себя по-разному

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост 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

Если тебе важна скорость работы можешь оставить библиотечную ассемблерную функцию, но при этом учитывать ее особенности. Например, если тебе нужно старое значение - можешь создать его копию.

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

Спасибо: 0 
ПрофильЦитата Ответить



Пост 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

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост 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


ты невнимательно читаешь. Речь идет о том, что при невольном использовании ассемблерной функции твой фрагмент становится эквивалентен передаче по ссылке

Спасибо: 0 
ПрофильЦитата Ответить



Пост N: 75
Зарегистрирован: 29.07.05
ссылка на сообщение  Отправлено: 03.03.10 17:23. Заголовок: suv2 пишет: ты невн..


suv2 пишет:

 цитата:
ты невнимательно читаешь. Речь идет о том, что при невольном использовании ассемблерной функции твой фрагмент становится эквивалентен передаче по ссылке

suv2 пишет:

 цитата:
После - не в следствии. Давай я не буду гадать, что ты там еще напутал и поменял, когда добавил скобки. Ты мог изменить порядок линковки библиотек, мог еще чего-то поменять, не заметить и так далее. Повторяю - 1) return (ansi) и return ansi - это ОДНО И ТО ЖЕ 2) никогда и ни при каких обстоятельствах на клиппер ты не сможешь изменить параметр внутри функции, если он не передавался по ссылке. Если ты утверждаешь, что 1) и 2) неверно

Я всегда свято в это верил. А насчёт поменял - так только скобки
suv2 пишет:

 цитата:
ты невнимательно читаешь. Речь идет о том, что при невольном использовании ассемблерной функции твой фрагмент становится эквивалентен передаче по ссылке

та чтобы там не делалось оно делается с cAnsi причём тут cOem?


Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 141
Зарегистрирован: 24.09.05
ссылка на сообщение  Отправлено: 03.03.10 17:26. Заголовок: les пишет: та чтобы..


les пишет:

 цитата:
та чтобы там не делалось оно делается с cAnsi причём тут cOem?



Я же объяснял - если функция на ассемблере - она может поменять что угодно. Даже если ты передавал по значению, а не по ссылке. Это же ассмеблер)

Вот это для кого написано было? - "Обычно, при программировании на ассемблере под клиппер необходимо прилагать значительные усилия, чтобы не изменить параметр - выделять память (а вдруг переменная большая (64К) и в данный момент такого куска свободной памяти не будет, что тогда?), копировать туда значение. Поэтому возникает соблазн большой получить ссылку на параметр (про который в руководстве по экстенд систем сказано - менять его НЕЛЬЗЯ) и сделать перекодировку непосредственно там, при этом переменная конечно же портится."

Другими словами. Функция на ассемблере может напрямую работать с переданным параметром и это ее личное дело, создавать ли копию этого параметра, чтобы он не изменился или не создавать. Это только в языках высокого уровня автоматически без твоего участия происходит передача по значению и ты думаешь, что это происходит само-собой. Но на самом деле для передачи по значению необходимо прилагать определенные программные усилия, на которых программисты экономят. Для ассемблера возможно всё - можно изменить что угодно, хоть переменную внутри функции, хоть переменную в другой программе, запущенной до текущей, хоть любой произвольный участок памяти. Функция спрашивает у клиппера адрес параметра и меняет его, не соблюдая никаких соглашений по видимости и по передаче параметров.

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

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник


Пост N: 359
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 03.03.10 18:53. Заголовок: suv2 пишет: Обычно,..


suv2 пишет:

 цитата:
Обычно, при программировании на ассемблере под клиппер необходимо прилагать значительные усилия, чтобы не изменить параметр - выделять память (а вдруг переменная большая (64К)



В Clipper никакая переменная не может быть больше 64K. Максимальный размер строковой переменной меньше, чем 64K, за счет специального префикса, который выдяется под системные нужды. По крйней мере 14 байтов надо вычесть из 64K.

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 142
Зарегистрирован: 24.09.05
ссылка на сообщение  Отправлено: 04.03.10 02:45. Заголовок: Григорьев Владимир п..


Григорьев Владимир пишет:

 цитата:
В Clipper никакая переменная не может быть больше 64K


читай внимательно, там не написано "больше 64к", там написано "большая (64к)"

Спасибо: 0 
ПрофильЦитата Ответить



Пост N: 76
Зарегистрирован: 29.07.05
ссылка на сообщение  Отправлено: 04.03.10 11:54. Заголовок: suv2 пишет: Функция..


suv2 пишет:

 цитата:
Функция спрашивает у клиппера адрес параметра и меняет его, не соблюдая никаких соглашений по видимости и по передаче параметров.

В моей ф-и OemToAnsi используется ф-я CharRepl() из CT III от CA, и я сомневаюсь что её писал школьник
suv2 пишет:

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

Моя ф-я на Clipper 5.2e

 цитата:
И никакие скобки не при чем.

Не спорю, но тем не менее... мистика
Кстати тестовый пример работает как со скобками так и без.



Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 143
Зарегистрирован: 24.09.05
ссылка на сообщение  Отправлено: 04.03.10 13:19. Заголовок: les пишет: Кстати т..


les пишет:

 цитата:
Кстати тестовый пример работает как со скобками так и без.


Всё, тупик. абсолютно бессодержательный ответ. Могу лишь повторить выводы.
Никакой порчи переменных на клиппер получить нельзя. Тестового примера нет и НЕ БУДЕТ
Переменные у тебя портит другая функция с таким же именем OemToAnsi, написанная похабно.
return (Ansi) и return Ansi - это одно и то же, между ними нет НИКАКОЙ разницы

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник


Пост N: 360
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 04.03.10 16:33. Заголовок: les пишет: В моей ф..


les пишет:

 цитата:
В моей ф-и OemToAnsi используется ф-я CharRepl() из CT III от CA, и я сомневаюсь что её писал школьник



На самом деле функции из этой библиотеки написаны крайне плохо! Как-то был вопрос по поводу одной функции здесь на форуме, и, отвечая на вопрос, я ее восстановил по объектному коду. Могу подтвердить, что та функция написана бездарно и с ошибками. Так что не следует доверять этой библиотеке. Ее код крайне некачественный.

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 144
Зарегистрирован: 24.09.05
ссылка на сообщение  Отправлено: 04.03.10 17:46. Заголовок: Григорьев Владимир п..


Григорьев Владимир пишет:

 цитата:
На самом деле функции из этой библиотеки написаны крайне плохо!


+1. И сам клиппер написан препохабнейше. обращения к неинициализированным переменным, запутанная логика, излишние усложнения, отсутствие контроля ошибок. но цэ-тулз - это нечто из ряда вон

Спасибо: 0 
ПрофильЦитата Ответить
Администратор




Пост N: 1340
Зарегистрирован: 23.05.05
ссылка на сообщение  Отправлено: 10.03.10 12:03. Заголовок: К слову. Пишу сейчас..


К слову.
Пишу сейчас на харборе, и получил по лбу граблями, описанными в этой теме.
В функции на С не сделал копию Item, и в результате после работы функции параметр изменил значение

Спасибо: 0 
ПрофильЦитата Ответить
Ответ:
1 2 3 4 5 6 7 8 9
большой шрифт малый шрифт надстрочный подстрочный заголовок большой заголовок видео с youtube.com картинка из интернета картинка с компьютера ссылка файл с компьютера русская клавиатура транслитератор  цитата  кавычки моноширинный шрифт моноширинный шрифт горизонтальная линия отступ точка LI бегущая строка оффтопик свернутый текст

показывать это сообщение только модераторам
не делать ссылки активными
Имя, пароль:      зарегистрироваться    
Тему читают:
- участник сейчас на форуме
- участник вне форума
Все даты в формате GMT  3 час. Хитов сегодня: 18
Права: смайлы да, картинки да, шрифты да, голосования нет
аватары да, автозамена ссылок вкл, премодерация откл, правка нет