Поле len используется нами для собственных нужд и указывает на способ работы с памятью этой строки. Поэтому Вам лучше не трогать его - это никак не повлияет на работоспособность.
А можно прояснить - когда и как выделяется буфер под строку, и когда и как он освобождается?
В приведенном выше примере, строка лежит в сегменте данных, и по идее, при попытке освобождения такой строки (а она ведь должна быть?) менеджер памяти должен выдать ошибку.
Можно поподробнее про "Поле len используется нами для собственных нужд и указывает на способ работы с памятью этой строки..."?
Как же все таки правильно вернуть строку из dll?
Renat, если в советнике будет сформирована строка длиной X символов, затем она передается в DLL (как pchar), и внутри DLL в эту строку поверх записывается строка длиной Y символов (Y < X) формата ASCIIZ.
Так можно делать?
Ладно, спрошу по другому... ;)
Renat, если в советнике будет сформирована строка длиной X символов, затем она передается в DLL (как pchar), и внутри DLL в эту строку поверх записывается строка длиной Y символов (Y < X) формата ASCIIZ.
Так можно делать?
Ладно, спрошу по другому... ;)
Renat, если в советнике будет сформирована строка длиной X символов, затем она передается в DLL (как pchar), и внутри DLL в эту строку поверх записывается строка длиной Y символов (Y < X) формата ASCIIZ.
Так можно делать?
Может быть это имеется ввиду?
char* statstr = "static string";
void func1(MqlStr* strarr, int n) {
strcpy(strarr[n].string, statstr);
}
или
void func2(char* str) {
strcpy(str, statstr);
}
По уазателю strarr[n].string должна быть выделена память уже, иначе будет ошибка доступа по неверному адресу если strarr[n].string строка будет короче чем statstr.
Кстати, а вот код который привёл автор статьи может привести к утечке памяти, если, например, строка в массиве arr[n].string уже есть массив char при предаче его в функцию DLL.
То есть передавая массив строк MQL4 string[] с какими-то значениями, а затем присваивая новое значение указателю на строку в DLL мы можем привести к утечке памяти при вызове эксперта и функции из DLL на каждый новый тик. Прежняя то строка не удаляется же при этом. Или я заблуждаюсь?
void PutString(MqlStr *arr, int n)
{
arr[n].string=test;
}
Кстати, а вот код ниже может привести к утечке памяти, если, например, строка в массиве arr[n].string уже есть массив char
То есть передавая массив строк string[] с какими-то значениями, а затем присваивая новое значение указателю на строку мы можем привести к утечке памяти при вызове эксперта и функции из DLL на каждый новый тик. Или я заблуждаюсь?
void PutString(MqlStr *arr, int n)
{
arr[n].string=test;
}
Важно знать, что из DLL можно _изменять_ содержимое строки в пределах доступного размера, но нельзя подменять строковые буферы. К сожалению, нельзя даже сделать free/delete, а потом malloc/new, так как память для строк выделяется не в стандартном хипе через malloc/new, а в специальном строковом пуле.
По статическим строкам - это любые _прямые_ операции над статическими строками, заключенными в кавычки.
Кстати, а вот код ниже может привести к утечке памяти, если, например,
строка в массиве arr[n].string уже есть массив char
То есть передавая массив строк string[] с какими-то значениями,
а затем присваивая новое значение указателю на строку мы можем
привести к утечке памяти при вызове эксперта и функции из DLL
на каждый новый тик. Или я заблуждаюсь?
void PutString(MqlStr *arr, int n)
{
arr[n].string=test;
}
Важно знать, что из DLL можно _изменять_ содержимое строки в пределах доступного размера, но нельзя подменять строковые буферы. К сожалению, нельзя даже сделать free/delete, а потом malloc/new, так как память для строк выделяется не в стандартном хипе через malloc/new, а в специальном строковом пуле.
то есть если хотим передавать строки в эксперт из DLL то надо заранее проинициализировтаь строки максимальным значением типа
Эксперт: void testStringFunc() { string[] strArray = {"ccccccccccccccc", "ccc"}; dllFunc(strArray, 2); Print("strArray[0] = ", strArray[0]); Print("strArray[1] = ", strArray[1]); } DLL: EXP void __stdcall dllFunc(MqlStr* strArray, int n) { strcpy(strArray[0].string, "maximum 14 char"); strcpy(strArray[1].string, "123"); }
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
В документации (DLLSample), дескрипторы строк описаны как:
struct MqlStr
{
int len;
char *string;
};
Т.е. string - указатель на строку, завершенную нулем, и len - длинна этой строки.
Именно так я и передавал:
static char test[]="some string"; //строка статически расположена в сегменте данных dll
..........................................
void PutString(MqlStr *arr, int n)
{
arr[n].string=test;
arr[n].len=strlen(test);
}
В результате программа висла. Передав этой функции проинициализированный в эксперте массив строк,
и посмотрев в отладчике, что передается, с удивлением обнаружил, что во всех строках, поле len равно 0 !
У неинициализированного массива так же, во всех строках len=0, но там еще и string=0. Увидев это, перестал
присваивать значение полю len. Т.е. :
void PutString_1(MqlStr *arr, int n)
{
arr[n].string=test;
}
После этого всё заработало. Вопрос, правильно ли я поступил ? Действительно ли нужно лишь копировать в поле string
указатели, а len оставлять без изменения ?