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

 
Igor Makanu:

этот вариант знаю

Тогда деление на ноль.

 
fxsaber:

Тогда деление на ноль.

пн...была надежда, но как всегда только хардкор )))

 
Vict:

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

Согласен

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

WinAPI -> MQL5 x64

A100, 2018.05.29 14:11

Все правило было сказано. Если вы хотите чтобы работало всегда - нужно использовать ushort, а если вы хотите разбираться почему вдруг со string перестало работать (то что работало еще вчера) - то можно и string

 
Vict:

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


Вы навели меня на мысль проверить длину инициализированной строки в StringInit(out, 165, 32);

Справка StringInit гласит, что вторым параметром является длина строки, длина строки в моём понимании это количество символов строки.
В моём случае входящая строка имеет 164 символа, по этому во второй параметр я ставил 165, пробовал и больше *2, 330.

Используя memcpy_s с указателем,

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

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

Но вот вы натолкнули меня на мысль, и в StringInit(out, 1400, 32) я поставил не длину строки, а размер в байтах указателя.
И о чудо, строка стала без лишних выводимых символов, без проблем парсится, и не одной утечки.
Хочу заметить что именно с указателем в sizeof, без указателя строка плывёт.

Напрашивается вопрос к разработчикам, а корректна ли справка по StringInit  ???
Не перепутано ли, в справке или в самой функции StringInit, длина строки с размером строки?
В общем сейчас если использовать memcpy то корректно работает, если передаёшь размер указателя, и StringInit инициализируешь этим размером, а не длиной!

 
A100:

Согласен

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

 
A100:

Таким образом вы просто выделили буфер заведомо избыточного размера (отодвинули границу) и ошибка просто не проявляется - потому что она возникала именно на границе

Я тоже так думал, у строки длина 164, ставил 165, ставил 330.
330 это уже явно не граница длины строки, если строки считать в символах.
Оказывается все дело не в длине, а в размере байт.
Но вот справка говорит обратное, что в  StringInit  должна быть именно длина.

В общем как я понял, mql-овский тип string это указатель, и работать с этим типом нужно как с указателем.

 
Так же решил проверить получаемую строку в dll, на присутствие терминального нуля.
Нуль имеется
for (int index = 0; index <= wcslen(data); ++index)
   wcout << static_cast<int>(data[index]) << " ";
123 34 101 34 58 34 97 103 103 84 114 97 100 101 34 44 34 69 34 58 49 53 54 57 54 50 52 50 50 57 50 51 54 44 34 115 34 58 34 66 84 
67 85 83 68 84 34 44 34 97 34 58 49 54 54 50 49 57 49 55 53 44 34 112 34 58 34 56 50 48 50 46 49 48 48 48 48 48 48 48 34 44 34 113 
34 58 34 48 46 48 51 51 50 51 48 48 48 34 44 34 102 34 58 49 56 51 57 54 49 54 55 50 44 34 108 34 58 49 56 51 57 54 49 54 55 50 44 
34 84 34 58 49 53 54 57 54 50 52 50 50 57 50 51 49 44 34 109 34 58 116 114 117 101 44 34 77 34 58 116 114 117 101 125 0
 
Roman:

Если настаивайте, то будь по-вашему.

 
Roman:

Я тоже так думал, у строки длина 164, ставил 165, ставил 330.
330 это уже явно не граница длины строки, если строки считать в символах.
Оказывается все дело не в длине, а в размере байт.
Но вот справка говорит обратное, что в  StringInit  должна быть именно длина.

В общем как я понял, mql-овский тип string это указатель, и работать с этим типом нужно как с указателем.

mql-овский тип string это структура, которая содержит в себе указатель, длину строки и возможно что-то ещё.

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

И всегда следить чтобы не выйти за пределы строки.

Все изменения размеров строки только на стороне MQL.

На стороне DLL, нужно внимательно читать справку по функциям, которые Вы используете. Все Ваши проблемы только в этом.

sizeof( wchar_t* ) возвращает размер указателя. Это совсем не то, что Вам нужно.

 
Koldun Zloy:

mql-овский тип string это структура, которая содержит в себе указатель, длину строки и возможно что-то ещё.

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

И всегда следить чтобы не выйти за пределы строки.

Все изменения размеров строки только на стороне MQL.

На стороне DLL, нужно внимательно читать справку по функциям, которые Вы используете. Все Ваши проблемы только в этом.

sizeof( wchar_t* ) возвращает размер указателя. Это совсем не то, что Вам нужно.

Правильно, я выделяю буфер под строку out, и инициализирую её пробелами.
Далее передаю эту строку(указатель) в dll. 

string out;
StringInit(out, 1400, 32);

Func(out);

В dll в out копируются wchar_t* данные, то есть тоже указатель. По логике проблем не должно возникать.
Как я понимаю согласно справке, функция StringInit и должна задавать длину строки.
Но тут ещё с самой функцией StringInit непонятки, указывал длину строки, фигня лезла, указал размер указателя, всё заработало.
Не пойму о какой ручной передаче длины строки вы имели ввиду.

И если использовать sizeof(wchar_t) без указателя, то строка начинает плыть лишними символами, что вызывает проблему с парсингом и утечкой.
Для передачи строк в dll использовался пример Рената, из его статьи как писать dll.
Но вот почему то именно если передаю без указателя sizeof(wchar_t), то строка плывёт, а с указателем sizeof(wchar_t*) проблем нет.
Имне кажется логично, я же копирую строку как указатель, то и размер нужно передавать указателя, а не типа.

Причина обращения: