Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > как сложить две строки


Автор: xxxSleshxxx 29.12.2009, 12:40
Всем привет.
Помогите с проблемкой, у меня создан поток в чужом процессе, как в этом потоке можно сложить две переменных типа String?

вариант: 
Код

var
  c: PChar;
  a, b: String;
begin
  a:='Что за';
  MessageBox(0, PChar(a), 'PPC', 0);
  
  b:='дела?';
  MessageBox(0, PChar(b), 'PPC', 0);
  
  c:=PChar(a+b);
  MessageBox(0, c, 'PPC', 0);
end.


Приводит к падению приложения в котором я запускаю свой поток.

Хотя если сложить так:
Код

c:='Что за' + 'дела?';
MessageBox(0, c, 'PPC', 0);

то все ок! Я так понимаю тут что то напутано с типами?

Автор: Frees 29.12.2009, 12:52
Цитата(xxxSleshxxx @  29.12.2009,  15:40 Найти цитируемый пост)
 к падению

где и какому

Автор: xxxSleshxxx 29.12.2009, 12:58
Цитата(Frees @  29.12.2009,  12:52 Найти цитируемый пост)
где и какому

К вот такому 
Инструкция по адресу "xxxx" обратилась к памяти по адресу "aaaaa"  Память не может быть "read".

Автор: RomanEEP 29.12.2009, 13:03
как создается поток?

Автор: xxxSleshxxx 29.12.2009, 13:13
Цитата(RomanEEP @ 29.12.2009,  13:03)
как создается поток?

Поток создается черз функцию в advApiHook от Ms-Rem'a
Да и как это может быть связано? все работает отлично пока не делаю сложение 

Автор: artsb 29.12.2009, 13:24
PChar это указатель на строку. Вы не выделяете память. На сколько мне известно, делается это с помощью SetLength.

Добавлено через 1 минуту и 34 секунды
как-то так:
Код

var
  c: PChar;
  a, b: String;
begin
  a:='Что за';
  MessageBox(0, PChar(a), 'PPC', 0);
  
  b:='дела?';
  MessageBox(0, PChar(b), 'PPC', 0);

  SetLength(c, Length(a+b));
  c:=PChar(a+b);
  MessageBox(0, c, 'PPC', 0);
end.

Автор: Frees 29.12.2009, 13:35
Цитата(artsb @  29.12.2009,  16:24 Найти цитируемый пост)
SetLength(c, Length(a+b));  
c:=PChar(a+b);


выделил память и затер указатель на нее

чет тут нето или ....

Автор: xxxSleshxxx 29.12.2009, 14:00
Цитата(artsb @  29.12.2009,  13:24 Найти цитируемый пост)
делается это с помощью SetLength.


Что самое странное, так ето то что при вызове SetLength(c, 11); даже без дальнейшего сложения приложение сразу падает.

Хм.... а почему тогда 
вот так  c:='Что за' + 'дела?';    работает, а если только укажу что строка String то все приехали?

 smile 
ладно терять время с этой проблемкой не стал перенес подсчет в свое приложение и запись результата в реестр, а в потоке считываю значение переменной из реестра.
Но вопрос оставлю открытым интересно с чем это связанно.

Автор: Snowy 29.12.2009, 14:09
Попробуй обойтись без менеджера памяти.
Код
var
  a, b, c: PChar;
begin
  a := 'Что за ';
  MessageBox(0, PChar(a), 'PPC', 0);

  b := 'дела?';
  MessageBox(0, PChar(b), 'PPC', 0);

  GetMem(c, StrLen(a) + StrLen(b) + 2);
  lstrcpy(c, a); lstrcat(c, b);
  MessageBox(0, c, 'PPC', 0);
  FreeMem(c);
end;


Добавлено через 2 минуты и 54 секунды
Цитата(xxxSleshxxx @  29.12.2009,  14:00 Найти цитируемый пост)
вот так  c:='Что за' + 'дела?';    работает
Эта конструкция ещё на уровне компиляции превращается в c:='Что задела?';

Цитата(xxxSleshxxx @  29.12.2009,  14:00 Найти цитируемый пост)
а если только укажу что строка String то все приехали
А стринги управляются менеджером памяти, который у тебя неизвестно где.
Юзай тока PChar, без использования стрингов.

Автор: CodeMonkey 29.12.2009, 14:56
Цитата(xxxSleshxxx @  29.12.2009,  12:40 Найти цитируемый пост)
как в этом потоке можно сложить две переменных типа String?

А откуда у вас в чужом процессе переменные String? 

Вариант а: от своего менеджера памяти.
Ответ: ну так и складывайте их как обычно, как строки: a := a + b;

Вариант б: это чужой кусок памяти.
Ответ: скопируйте к себе и складывайте как хотите. Теоретически, должно сработать: StrVar := a + b; (память для StrVar уйдёт на наш менеджер памяти, а не чужой). Правда, тогда непонятно, зачем вы засунули чужую память в переменные a и b.

http://transl-gunsmoker.blogspot.com/2009/09/pchars.html.

Автор: xxxSleshxxx 29.12.2009, 19:09
Вот кусок кода, чтобы не было лишних вопросов.

Код

uses
  Windows, Dialogs, Classes, SysUtils, advApiHook;

var
  hk:hkey;
  p,d:DWORD;
  StartInf: TStartupInfo;
  ProcInf: TProcessInformation;
  rData: array[0..254] of char;

//-------------------------- Наш поток в апдейтере. ----------------------------
function ThreadUpdate(dwEntryPoint: Pointer; name: string): THandle; stdcall;
var
  hwUpdate: HWND;
  PathProg: String;
  begin
    LoadLibrary('kernel32.dll');
    LoadLibrary('user32.dll');

    p:=REG_SZ;
    d:=254;
    RegOpenKey(HKEY_CURRENT_USER, 'Software\MixLine', hk);
    RegQueryValueEx(hk, 'Path', nil, @p, @rData, @d);
    RegCloseKey(hk);

    //Ждем пока апдейтер закончит проверку
    hwUpdate := 0;
    While hwUpdate = 0 do
      begin
        hwUpdate:=FindWindowEx(FindWindow('LAUNCHER', nil), 0, 'Static', 'Отсутствует подключение к сети');
        Sleep(200);
      end;

    //Скрываем апдейтер
    ShowWindow(FindWindow('LAUNCHER', nil), SW_HIDE);

    //Запускаем программу
    PathProg := rData + '\MixLine.exe';     //Вот тут все и падает!!! а если заместо сложения написать полный путь 'C:\Program Files (x86)\MixLine\MixLine.exe' то все гуд.

    ZeroMemory(@StartInf, SizeOf(TStartupInfo));
    CreateProcess(nil, rData, nil, nil, false, 0, nil, nil, StartInf, ProcInf);
  end;
//---------------------------------- Конец. ------------------------------------
//------------------------------------------------------------------------------
//---------------------------- Запуск апдейтера. -------------------------------
procedure StartUpdate;
var
  PathUpdate: String;
  begin
    p:=REG_SZ;
    d:=254;
    RegOpenKey(HKEY_CURRENT_USER, 'Software\MixLine', hk);
    RegQueryValueEx(hk, 'Path', nil, @p, @rData, @d);
    RegCloseKey(hk);

    //запускаем апдейтер
    PathUpdate := rData + '\Patcher\Updater.exe';
    ZeroMemory(@StartInf, SizeOf(TStartupInfo));
    CreateProcess(nil, PChar(PathUpdate), nil, nil, false, 0, nil, nil, StartInf, ProcInf);
    Sleep(200);

    //внедряем в апдейтер наш поток
    InjectThisExe(ProcInf.hProcess, @ThreadUpdate)
  end;
//---------------------------------- Конец. ------------------------------------
//------------------------------------------------------------------------------
begin
  StartUpdate;
end.


Есть программа которую запускает лаунчер после проверки целосности и обновления программы
суть в том что лаунчер не стартует прогу без инета, а есть потребность в использовании там где его нет!!! и на примую прогу нельзя запускать без лаунчера. Ну суть собственно не в том зачем я это пишу
а почему в потоке не складываются переменные типа String и как говорил Snowy без менеджера памяти тоже пробовал результат один ошибка чтения памяти.

Автор: CodeMonkey 29.12.2009, 22:12
PathProg заменяете на array[0..MAX_PATH] of Char и копируйте в него сначала rData, потом константу.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)