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

 
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*) проблем нет.
Имне кажется логично, я же копирую строку как указатель, то и размер нужно передавать указателя, а не типа.

[Удален]  

Попробуйте

StringInit(out, 200, 32);
...

if ( memcpy_s(out, 200*sizeof(wchar_t), data, wcslen(data)*sizeof(wchar_t)+sizeof(L'\0')) ) {
   // что-то пошло не так
}

После того как это сработает, я бы обратите внимание на wcscpy.


 
Vict:

Попробуйте

После того как это сработает, я бы обратите внимание на wcscpy.


Нет, так не сработало, строка не передается, но и проблем не возникает.
А вот так без нуля сработало, но так плывёт конец строки лишними символами.

StringInit(out, 200, 32);
if (memcpy_s(out, 200 * sizeof(wchar_t), data, wcslen(data) * sizeof(wchar_t)))     // + sizeof(L'\0'))) 
{
   MessageBoxW(NULL, L"Problem", L"Problem", MB_OK);
}
 
Инициализирую размером указателя, и в memcpy использую указатель, так всё норм :)) 
StringInit(out, 1400, 32);

if (memcpy_s(out, 200 * sizeof(wchar_t*), data, wcslen(data) * sizeof(wchar_t*)))  
{
   MessageBoxW(NULL, L"Problem", L"Problem", MB_OK);
}
 
Roman:


Нет, так не сработало, строка не передается, но и проблем не возникает.
А вот так сработало, но снова плывёт конец строки лишними символами.

Читаем внимательно доки по std::wcslen

Returns the length of a wide string, that is the number of non-null wide characters that precede the terminating null wide character.

Если don't undestand, то гугл хелп ми:

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

#include <iostream>
#include <cwchar>

int main()
{
        const wchar_t* text = L"12345";
        std::cout << std::wcslen(text);
        return 0;
}
Запускаем и видим:

Переписываем:

if (memcpy_s(out, 200 * sizeof(wchar_t), data, (wcslen(data)+1) * sizeof(wchar_t))) 

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

Примерно так и происходит.

PS. Это С, это хардкор, тут форумы курить не стоит, только серьезные издания и доки, только свои мозги.