На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! ПРАВИЛА РАЗДЕЛА · FAQ раздела Delphi · Книги по Delphi
Пожалуйста, выделяйте текст программы тегом [сode=pas] ... [/сode]. Для этого используйте кнопку [code=pas] в форме ответа или комбобокс, если нужно вставить код на языке, отличном от Дельфи/Паскаля.
Следующие вопросы задаются очень часто, подробно разобраны в FAQ и, поэтому, будут безжалостно удаляться:
1. Преобразовать переменную типа String в тип PChar (PAnsiChar)
2. Как "свернуть" программу в трей.
3. Как "скрыться" от Ctrl + Alt + Del (заблокировать их и т.п.)
4. Как прочитать список файлов, поддиректорий в директории?
5. Как запустить программу/файл?
... (продолжение следует) ...

Вопросы, подробно описанные во встроенной справочной системе Delphi, не несут полезной тематической нагрузки, поэтому будут удаляться.
Запрещается создавать темы с просьбой выполнить какую-то работу за автора темы. Форум является средством общения и общего поиска решения. Вашу работу за Вас никто выполнять не будет.


Внимание
Попытки открытия обсуждений реализации вредоносного ПО, включая различные интерпретации спам-ботов, наказывается предупреждением на 30 дней.
Повторная попытка - 60 дней. Последующие попытки бан.
Мат в разделе - бан на три месяца...
Модераторы: jack128, D[u]fa, Shaggy, Rouse_
  
> PAnsiChar и потоки , интересный глюк
    Доброго времени суток. Есть простой код
    ExpandedWrap disabled
      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 однотипных строки.
    ExpandedWrap disabled
      if NOT fileexists(PATH+filename1) then ...
      if NOT fileexists(PATH+filename2) then ...

    После выполнения первой из них (с данными все в порядке) происходит что-то непонятное, в переменную PATH в конец дописывается filename1, а первая часть значения теряется, потому вторая строчка и вылетает. Но это все зависит от того, заполняется ли переменная в 1м потоке или во 2м...
    Сообщение отредактировано: Виталь -
      Цитата Виталь @
      Есть простой код
      ExpandedWrap disabled
        ...
        PATH := Pchar(extractfilepath(exeFileName));
        ...

      Простой и неправильный.
      PAnsiChar это просто указатель на какую-то "внешнюю" строку (или часть строки). Этот указатель является валидным до тех пор, пока строка, на которую он указывает, существует. А ты переменной PATH присваиваешь указатель на временную строку (возвращаемую функцией extractfilepath), которую компилятор вправе удалить в любой момент после ее использования. Так делать нельзя, т.к. это приводит к непредсказуемым последствиям. Как в твоем случае - при присвоении PATH в Execute потока, временная строка сохраняется до выхода из Execute, поэтому "всё работает" (хотя полагаться на это нельзя, т.к. компилятор мог использовать эту же временную переменную и для других временных строк, поэтому на момент использования PATH может указывать вовсе не на ту строку, которую ты ожидаешь). В случае же присваивания PATH в begin..end dll, временная строка может удаляться\переписываться после выполнения блока begin..end (т.к. это не какой-то "глобальный" код, а часть функции DllMain, которая выполняется один раз при загрузке библиотеки в процесс). Соотв-но на момент использования указателя PATH в потоке, он указывает не на валидную строку, а на какой-то мусор.

      Вывод: PATH нужно объявлять не как указатель PAnsiChar на какую-то внешнюю строку, а как массив символов AnsiChar, в который копируется внешняя строка
      ExpandedWrap disabled
        PATH:array[0..255] of AnsiChar; //по сути это тот же PAnsiChar, но указывающей на собственную строку символов
        StrPCopy(PATH,ExtractFilePath(exeFileName));


      Цитата Виталь @
      Нет, я конечно могу вернуться к использованию типа string

      Ты и так используешь тип string, только неявно - в функциях extractfilepath, fileexists и т.п.
        Понял, спасибо.
        Вернулся к string везде в коде включая переписанные функции, принимавшие раньше pchar.
          Цитата Виталь @
          Вернулся к string везде в коде включая переписанные функции, принимавшие раньше pchar.

          Только в параметрах экспортируемых функций string не делай, иначе бед не оберешься
          0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
          0 пользователей:


          Рейтинг@Mail.ru
          [ Script execution time: 0,0226 ]   [ 16 queries used ]   [ Generated: 24.04.24, 18:43 GMT ]