Ошибки, баги, вопросы - страница 2576

 
Vict:

Прикольные такие примеры у вас, всё убрали, оставили UB (модификация строковых литералов), а все телепатить должны. Если рассчитывайте на какой-то толковый совет, то приведите минимальный рабочий код (на двух сторонах), иначе просто трёп.

В примере показано то место которое вызывает проблему, то есть проблема в копировании указателя wchar_t* в mql-овкий string.
Остальной код не относящийся к проблеме, не несёт полезной нагрузки, так как всего лишь выполняет проверку if данные есть, тогда читаем, и т.д.
Зачем его писать в пример и засорять саму суть проблемы, когда даже с упрощённым кодом многие не поймут в чём суть проблемы.
Поймите getData() сетевая функция, которая читает  FrameOpcode, и возвращает полученные данные в виде указателя на строку типа const wchar_t*.

Всем известно что простая функция wcscpy(out, data) копирует  const wchar_t* строку,  в  строку wchar_t*, и автоматически считает длину символов до терминального нуля  const wchar_t* 
Вот тут то и проявляется ошибка, mql-овский string не корректно принимает скопированную строку wchar_t*, вопрос почему такое может быть? Если функция автоматически определяет терминальный ноль.
В статье Рената строки копируются через memcpy с допущенной ошибкой по размеру байтов. Возможно такой же подход используется в самом коде терминала, для формирования mql-овского типа string.
Понимаете, 
memcpy  не только не подходит для копирования строк, так ещё и с ошибкой в размере переданных байт, приводит к неровным данным.
Для копирования строк ведь есть другие специальные для этого Сишные функции, такие как wcscpy,  wcsncpy и т.д.
Да и сам Ренат в одной из веток писал, что вскоре будут полностью перерабатывать работу со строками, видимо проблема известна, но почему то тишина в ответ на обозначенную мной проблему.

Вот для сравнения размер байт указателя wchar_t*, и простого типа wchar_t

Файлы:
1.PNG  83 kb
 
Roman:

Кончено, проще написать целую портянку в ответ, чем нормальный воспроизводимый тест заменив getData() на что-то. Чего ожидаете, если UB на UB, и выводы неверны:

memcpy(cp,to,wcslen(to)*sizeof(wchar_t));  //в этой строке должен быть указатель sizeof(wchar_t *)

всё там правильно. Что-то не так с вашими представлениями о строках, отсюда и обшибки.

 
Vict:

Кончено, проще написать целую портянку в ответ, чем нормальный воспроизводимый тест заменив getData() на что-то. Чего ожидаете, если UB на UB, и выводы неверны:

всё там правильно. Что-то не так с вашими представлениями о строках, отсюда и ошибки.

Воспроизводимый код предоставить нет возможности, так как сами понимаете что это dll, использующая сторонние библиотеки.
По поводу почему я решил что в примере ошибка.
memcpy(cp,to,wcslen(to)*sizeof(wchar_t));  //в этой строке должен быть указатель sizeof(wchar_t *)

Используя функцию без указателя,

memcpy(out, data, wcslen(data) * sizeof(wchar_t));

то конец строки начинает плыть лишними символами. Посмотрите на конец строки на снимке.
Да и логично же, что если мы копируем строку wchar_t* как указатель, то и нужно передавать размер указателя, а не размер типа.

А если использую указатель,

memcpy(out, data, wcslen(data) * sizeof(wchar_t*));

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

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

wcsncpy(out, data, wcslen(data));

Вот и перебираю кучу вариантов где может быть причина, но используя memcpy без указателя в sizeof, результат виден на скрине.

Хочу ещё проверить полученную wchar_t* строку на терминальный ноль, есть он или нет.
Как это можно сделать?

Файлы:
 
Используя функцию без указателя,

тут out останется без \0 в конце

А если использую указатель,

тут вы выходите за границы out

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

опять out останется без \0. Смотрите доки

wcsncpy, wcsncpy_s

...

If countis reached before the entire string srcwas copied, the resulting wide character array is not null-terminated.

...

ЗЫ: может не связываться со строками вообще? сохраняйте в wchar_t массивы и гоняйте их, а внутри мкл конвертировать в строку если надо https://www.mql5.com/ru/docs/convert/shortarraytostring

 
Vict:

ЗЫ: может не связываться со строками вообще? сохраняйте в wchar_t массивы и гоняйте их, а внутри мкл конвертировать в строку если надо

О, сенкю )), за подсказку, что wcsncpy обрезает ноль.
Да массивы оставил на последок, если не получится с указателями, то буду юзать массивы.

 

Движок форума не позволяет сделать пост из одной картинки. Требует ввода текста.

Приходится ставить пробел.

 
fxsaber:

Движок форума не позволяет сделать пост из одной картинки. Требует ввода текста.

Приходится ставить пробел.

Вроде всё логично: это форум и главное это текст. А картинка прикладывается по сколько постольку. Здесь ведь не кладбище картинок.

 

дописал код, работает в MT4/5, столкнулся небольшой неожиданностью

а чем в MQL4  можно заменить TesterStop()

?

 
Igor Makanu:

а чем в MQL4  можно заменить TesterStop()?

ExpertRemove.

 
fxsaber:

ExpertRemove.

этот вариант знаю, но видел сообщения, что ExpertRemove(0 нельзя для экспертов для Маркета использовать, может соберусь в Маркет выложить, придется опять переделывать

в общем использую TesterStop() в двух случаях:

- вместо INIT_PARAMETERS_INCORRECT , чтобы скрыть лог оптимизатора

- если недостаточно средств для открытия ордера, ордер то не открываю, а тест завершаю, что оптимизация быстрее шла