использование FpExecVPE [Решено]

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Ответить
Аватара пользователя
coyot.rush
постоялец
Сообщения: 309
Зарегистрирован: 14.08.2009 08:59:48

использование FpExecVPE [Решено]

Сообщение coyot.rush »

Сделал функцию обертку для FpExecVPE (необходимо перекрыть переменные окружения ). Снова наткнулся на те же грабли что и с execve http://www.freepascal.ru/forum/viewtopic.php?f=13&t=6909
при запуске env переменные окружения "плывут" . Хотя вывод на консоль через writeln('EnvironmentString('+inttostr(i)+')='+GetEnvironmentString(i)) нормальный

Код: Выделить всё

function RunApp(PathToBin:string): integer;
var
PParam,PEnv:PPChar;
i:integer;
ce:integer;
begin
 Getmem(PParam,(Paramcount+1)*SizeOf(Pchar));
 Writeln('Paramcount='+inttostr(Paramcount+1));
 for i:=0 to Paramcount-1 do
 begin
  PParam[i]:=Pchar(ParamStr(i));
  writeln('ParamStr('+inttostr(i)+')='+ParamStr(i));
 end;
 PParam[Paramcount+1]:=nil;
 ce:=GetEnvironmentVariableCount;
 Getmem(PEnv,(ce+1)*SizeOf(Pchar));
 writeln('EnvironmentVariableCount='+inttostr(ce));
 for i:=0 to ce-1 do
 begin
  PEnv[i]:=Pchar(GetEnvironmentString(i));
  writeln('EnvironmentString('+inttostr(i)+')='+GetEnvironmentString(i));
 end;

 PParam[GetEnvironmentVariableCount+1]:=nil;

 FpExecVPE(PathToBin,PParam,PEnv);
end;
Последний раз редактировалось coyot.rush 02.05.2011 20:11:34, всего редактировалось 1 раз.
Аватара пользователя
coyot.rush
постоялец
Сообщения: 309
Зарегистрирован: 14.08.2009 08:59:48

Сообщение coyot.rush »

Проблему решил, но вопрос остался почему код приведенный выше работает не корректно :?:
Вот "обходной код"

Код: Выделить всё

function RunApp(PathToBin:string): integer;
var
PParam,PEnv:PPChar;
ce,cp,i:integer;
ListOfEnv:TStringList;
ListofParam:TStringList;
begin
 ListofParam:=TStringList.Create;
 cp:=Paramcount;
 for i:=0 to cp do
 begin
  ListofParam.Add(ParamStr(i));
 end;
 Getmem(PParam,(cp+1)*SizeOf(Pchar));
 for i:=0 to cp do
 begin
  PParam[i]:=Pchar(ListofParam[i]);
 end;
 PParam[cp+1]:=nil;
 ce:=GetEnvironmentVariableCount;
 ListOfEnv:=TStringList.Create;
 for i:=1 to ce-1 do
  begin
  ListOfEnv.Add(GetEnvironmentString(i));
 end;
 Getmem(PEnv,(ListOfEnv.Count+1)*SizeOf(Pchar));
 for i:=0 to ListOfEnv.Count-1 do
 begin
 Penv[i]:=Pchar(ListOfEnv[i]);
 end;
 Penv[ListOfEnv.Count]:=nil;
 Result:=FpExecVPE(PathToBin,PParam,PEnv);
 ListOfEnv.Free;
 ListofParam.Free;
end;
Mr.Smart
долгожитель
Сообщения: 1796
Зарегистрирован: 29.03.2008 00:01:11
Откуда: из леса!

Сообщение Mr.Smart »

В первом случае вы не выделяете память под строку.

Код: Выделить всё

 PEnv[i]:=strnew(Pchar(GetEnvironmentString(i)));

только после, нужно будет отчистить память

Код: Выделить всё

StrDispose(PEnv[i])
Аватара пользователя
coyot.rush
постоялец
Сообщения: 309
Зарегистрирован: 14.08.2009 08:59:48

Сообщение coyot.rush »

Во втором я тоже память не выделяю,для penv[i] ,но всё корректно работает :?:
Про strnew не знал, я так понимаю его применяют для массивов PPChar :?:
Тогда не понятно как работает конструкция PChar(SomeString), во многих API всё работает, и нет необходимости в ручном управление памятью :?:

Добавлено спустя 10 минут 42 секунды:
Я так понимаю, что результат функции возвращающий строку не может быть использован для передачи в API ситемы так как Result fpc обнуляет. А чтобы преобразовать в pchar нужно использовать уже существующую строку (strnew-выделяет памяти на куче для строки) :roll:
Mr.Smart
долгожитель
Сообщения: 1796
Зарегистрирован: 29.03.2008 00:01:11
Откуда: из леса!

Сообщение Mr.Smart »

Совершенно верно, выделяет и копирует её туда.
Во втором случае память вы выделяется в TStringList не явно.

Добавлено спустя 1 минуту 58 секунд:
Данную функцию применяю, когда нужно выделить память под строку и скопировать её. Не обязательно к массиву Pchar (PPChar).
Аватара пользователя
coyot.rush
постоялец
Сообщения: 309
Зарегистрирован: 14.08.2009 08:59:48

Сообщение coyot.rush »

Спасибо Mr.Smart
Данную функцию применяю, когда нужно выделить память под строку и скопировать её. Не обязательно к массиву Pchar (PPChar).

Например так

Код: Выделить всё

function SomeFunction():string;
begin
Result:='C:\';
end;
....
ShellExecute(handle,nil,strnew(SomeFunction),nil,nil,SW_SHOWNORMAL);
Mr.Smart
долгожитель
Сообщения: 1796
Зарегистрирован: 29.03.2008 00:01:11
Откуда: из леса!

Сообщение Mr.Smart »

Строку выделенную strnew необходимо освободить при помощи StrDispose!

Код: Выделить всё

var
  p: PCahr;
begin
   p:=strnew(SomeFunction);
   ShellExecute(handle,nil,p,nil,nil,SW_SHOWNORMAL);
   StrDispose(p);
Аватара пользователя
coyot.rush
постоялец
Сообщения: 309
Зарегистрирован: 14.08.2009 08:59:48

Сообщение coyot.rush »

Строку выделенную strnew необходимо освободить при помощи StrDispose!

Вот и утечка памяти :oops:
Почему тогда работает
ShellExecute(handle,nil,Pchar(SomeFunction),nil,nil,SW_SHOWNORMAL);

Распределение строки нету :?:
Mr.Smart
долгожитель
Сообщения: 1796
Зарегистрирован: 29.03.2008 00:01:11
Откуда: из леса!

Сообщение Mr.Smart »

Оно будет работать, почему бы ей не работать? Память просто не освобождается и всё.
Аватара пользователя
coyot.rush
постоялец
Сообщения: 309
Зарегистрирован: 14.08.2009 08:59:48

Сообщение coyot.rush »

ShellExecute(handle,nil,Pchar(SomeFunction),nil,nil,SW_SHOWNORMAL);

Оно будет работать, почему бы ей не работать? Память просто не освобождается и всё.
:shock:
И такое рекомендуют почти на всех сайтах по программированию на delphi :!: :!: :!:
Mr.Smart
долгожитель
Сообщения: 1796
Зарегистрирован: 29.03.2008 00:01:11
Откуда: из леса!

Сообщение Mr.Smart »

Тьфу просмотрел.
В данном случае удалением строки занимается менеджер памяти.
Аватара пользователя
coyot.rush
постоялец
Сообщения: 309
Зарегистрирован: 14.08.2009 08:59:48

Сообщение coyot.rush »

В данном случае удалением строки занимается менеджер памяти

и распределением
Ответить