Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.190.156.212] |
|
Сообщ.
#1
,
|
|
|
Доброго времени суток. Есть простой код
PATH : PAnsiChar; filename: string[20] = '*************'; PATHLEN : word; ... ... PATH := Pchar(extractfilepath(exeFileName)); PATHLEN := StrLen(PATH); ... ... if NOT fileexists(PATH+filename) then ... Все это находится в DLL, где при загрузке библиотеки создается новый поток и в нем много чего происходит. Переменные объявлены глобальные. Условие выполняется уже внутри создаваемого потока. Так вот. Если PATH и PATHLEN присвоить значение в begin...end кода библиотеки (поток вызывающего приложения) то при операции PATH+filename получится какая-то ерунда, выглядящая как последние 2 символа строки PATH, неизвестно откуда взявшийся перевод строки и далее filename. Если же PATH и PATHLEN заполнять уже внутри созданного потока то все работает. Больше нигде эти переменные не используются, порча данных не должна происходить. У кого-то есть идеи с чем это связано? Нет, я конечно могу вернуться к использованию типа string но хотелось бы понять... Уточнение. В коде 2 однотипных строки. if NOT fileexists(PATH+filename1) then ... if NOT fileexists(PATH+filename2) then ... После выполнения первой из них (с данными все в порядке) происходит что-то непонятное, в переменную PATH в конец дописывается filename1, а первая часть значения теряется, потому вторая строчка и вылетает. Но это все зависит от того, заполняется ли переменная в 1м потоке или во 2м... |
Сообщ.
#2
,
|
|
|
Цитата Виталь @ Есть простой код ... PATH := Pchar(extractfilepath(exeFileName)); ... Простой и неправильный. PAnsiChar это просто указатель на какую-то "внешнюю" строку (или часть строки). Этот указатель является валидным до тех пор, пока строка, на которую он указывает, существует. А ты переменной PATH присваиваешь указатель на временную строку (возвращаемую функцией extractfilepath), которую компилятор вправе удалить в любой момент после ее использования. Так делать нельзя, т.к. это приводит к непредсказуемым последствиям. Как в твоем случае - при присвоении PATH в Execute потока, временная строка сохраняется до выхода из Execute, поэтому "всё работает" (хотя полагаться на это нельзя, т.к. компилятор мог использовать эту же временную переменную и для других временных строк, поэтому на момент использования PATH может указывать вовсе не на ту строку, которую ты ожидаешь). В случае же присваивания PATH в begin..end dll, временная строка может удаляться\переписываться после выполнения блока begin..end (т.к. это не какой-то "глобальный" код, а часть функции DllMain, которая выполняется один раз при загрузке библиотеки в процесс). Соотв-но на момент использования указателя PATH в потоке, он указывает не на валидную строку, а на какой-то мусор. Вывод: PATH нужно объявлять не как указатель PAnsiChar на какую-то внешнюю строку, а как массив символов AnsiChar, в который копируется внешняя строка PATH:array[0..255] of AnsiChar; //по сути это тот же PAnsiChar, но указывающей на собственную строку символов StrPCopy(PATH,ExtractFilePath(exeFileName)); Цитата Виталь @ Нет, я конечно могу вернуться к использованию типа string Ты и так используешь тип string, только неявно - в функциях extractfilepath, fileexists и т.п. |
Сообщ.
#3
,
|
|
|
Понял, спасибо.
Вернулся к string везде в коде включая переписанные функции, принимавшие раньше pchar. |
Сообщ.
#4
,
|
|
|
Цитата Виталь @ Вернулся к string везде в коде включая переписанные функции, принимавшие раньше pchar. Только в параметрах экспортируемых функций string не делай, иначе бед не оберешься |