LINUX.ORG.RU

[C] помогите с exevp

 


0

0

Гуголь так напряг, что он меня почти забанил=(

Проблема следующая

debian lenny x86_64 при вызове execvp() errno получаю 14

[EFAULT] Длинa нoвoгo фaйлa oбpaзa нe coвпaдaeт c yкaзaннoй в зaгoлoвкe. [EFAULT] Aдpec, зaдaнный path, argv или envp, выxoдит зa пpeдeлы пoльзoвaтeльcкoгo aдpecнoгo пpocтpaнcтвa пpoцecca.

вот что нагуглил.

скажите, в куда копать? path проверял, вроде как все в порядке. запускаю cp который лежит в /bin/cp

> [EFAULT] Aдpec, зaдaнный path, argv или envp, выxoдит зa пpeдeлы пoльзoвaтeльcкoгo aдpecнoгo пpocтpaнcтвa пpoцecca.

И что непонятно?

Ты бы код вызова привел.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

непонятно то, что это рабочий заведомо код

int open_fork_execlp(const char *path, const char *mode, const char *file, char *const arg, ...) { .... switch((pid = fork())) { case 0: ... execvp(file, &arg); .... }

}

open_fork_execlp(NULL, NULL,"cp", "cp", file1, file2, NULL);

прбовал /bin/cp указывать непосредственно - тоже самое

Borman3000
() автор топика
Ответ на: комментарий от Borman3000

> int open_fork_execlp(const char *path, const char *mode, const char *file, char *const arg, ...) { .... switch((pid = fork())) { case 0: ... execvp(file, &arg); .... }

Думаю, у тебя неправильный формат 2-го аргумента execvp. Последний элемент массива должен быть нулевым указателем, у тебя это не так.

execl(file, file, arg, NULL), насколько я помню.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

open_fork_execlp(NULL, NULL,"cp", "cp", file1, file2, NULL); вот тут есть это NULL

проблема тут скорее не в коде, а с каким-то дополнительными настройками в системе, нет? Это не я код пишу, а пытаюсь завести заведомо рабочий проект, прекрасно работающий на еще десятке машинок. Неужели никто не сталкивался? Такая ошибка на ЛЮБЫЕ корректные пути и запросы. Если сделать вызов с ошибкой (спровоцировать) все ошибки отрабатывают

Borman3000
() автор топика
Ответ на: комментарий от Borman3000

> проблема тут скорее не в коде, а с каким-то дополнительными настройками в системе, нет?

Нет.

> пытаюсь завести заведомо рабочий проект

Умник, который писал open_fork_exec, написал ненужный хак для поднятия ЧСВ. Этот хак не обязан работать. Сделай, как я сказал - если заработает, значит 100% виноват код.

tailgunner ★★★★★
()
Ответ на: комментарий от Borman3000

> к сожалению безрезультатно

Кхм. Прога вида:

#include <unistd.h>

int main()
{
execl("/bin/ls", "/bin/ls", "/", NULL);
}

не работает? У тебя вообще что-нибудь работает? :)

tailgunner ★★★★★
()
Ответ на: комментарий от Borman3000

Минимальный исходник с воспрозводимой проблемой можешь дать?

mv ★★★★★
()
Ответ на: комментарий от tailgunner

http://pastebin.com/m3ca1b165

вот кусок кода. на локальной машине выводит содержимое /

linux-n9zp:/home/borman3000/Test # gcc test.c linux-n9zp:/home/borman3000/Test # ./a.out bin boot dev dos etc home lib lost+found media mnt opt proc root sbin srv sys tmp usr var bin boot dev dos etc home lib lost+found media mnt opt proc root sbin srv sys tmp usr var

на проблемной

stp4-11:~# gcc test.c stp4-11:~# ./a.out ls: cannot access ls: No such file or directory ls: cannot access ls: No such file or directory

Borman3000
() автор топика
Ответ на: комментарий от Borman3000

int open_fork_execlp(const char *path, const char *mode,
		     const char *file, char *const arg, ...) {
...
	execvp(file, &arg);

Что этот бред с &arg в задумке аффтара означать должен?

mv ★★★★★
()
Ответ на: комментарий от mv

Ну видимо пытались сделать "универсальную" функцию, что ли.

Так не подскажите почему может PATH не видеть этот код?

Borman3000
() автор топика
Ответ на: комментарий от Borman3000

> Так не подскажите почему может PATH не видеть этот код?

Так дело не в том, что execvp неправильно работает, а в том, что код неправильный. Я даже смею предположить, что машина на которой код "работает" - 32-битная, а на которой "не работает" - 64-битная. Почему не работает - читать про переменное число аргументов функции в Си, а также C calling convention на x86 и x86-64.

mv ★★★★★
()
Ответ на: комментарий от Borman3000

Вот ещё для размышлений:

#include <unistd.h>

int open_fork_execlp(const char *path, const char *mode,
		     const char *file, char* const arg[]) {
	pid_t pid;
	int status;

	execvp(file, arg);

}

int main()
{
	char* const args[] = {"ls", "/", NULL};
	open_fork_execlp(NULL, NULL,"ls", args);
}

mv ★★★★★
()
Ответ на: комментарий от mv

Ты прав. Я вообще подозревал что в архитектуре дело, но не был до конца уверен.

А не сложно будет гуру подсказать как можно закостылять этот кусок кода, чтобы он сносно работал? если это не сложно. я просто на с++ пишу в основном и на java, тяжело мне с Си=(

Borman3000
() автор топика
Ответ на: комментарий от mv

Это вариант мне пришел в голову тоже, уже даже опробовал. Но нормальный кусок кода надо попроавить. А както закостылять функцию саму реально?

Borman3000
() автор топика
Ответ на: комментарий от Borman3000

Собирай нормальный массив указателей в самой функции с помощью va_start/va_arg/va_end и передавай уже его в execvp. Взятие адреса аргумента функции - это бред чистой воды, поэтому на x86-64 оно не работает, т.к. x86-64 первые 6 аргументов передает через регистры, а x86 (32 бита) - только 3. Если arg в той мега-функции поставишь, скажем, третим аргументом, то и на 32 битах код перестанет работать.

Так что или правильно вручную геморроиться со сборкой массива в самой функции, либо уже передавать сформированным.

mv ★★★★★
()

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

по сабжу могу сказать, что твоя версия действительно не работает под 64 бита,
т.к. является устаревшей, судя по всему аж прошлогодней, а то и раньше.
и дело не только в этой функции, а в коде файлов th_* и thread_* =)
и кстати, а у тебя есть исходники виндового "модуля"?

бугага, сюрприз?

grey_a
()
Ответ на: комментарий от grey_a

Если честно не сюрприз. Судя по коду, я был уверен что автор тут обитает=)

Попали "случайно". Могу в жабере рассказать коварную историю, если конечно оно тебе надо=)

Borman3000
() автор топика
Ответ на: комментарий от grey_a

Привет, разработчик. Ну и весёлый у вас там код :).

Скажи назавание продукта чтобы я случайно не купил. Шутка, не принимай близко к сердцу :).

true_admin ★★★★★
()
Ответ на: комментарий от mv

> x86-64 первые 6 аргументов передает через регистры, а x86 (32 бита) - только 3. Если arg в той мега-функции поставишь, скажем, третим аргументом, то и на 32 битах код перестанет работать.

На x86 все аргументы передаются через стек, так что работать должно бы всегда, но я бы не поставил на это и рубля :) А с включенной оптимизацией, если компилятор захочет заинлайнить вызов, можно вообще получить что угодно.

const86 ★★★★★
()
Ответ на: комментарий от const86

> На x86 все аргументы передаются через стек, так что работать должно бы всегда, но я бы не поставил на это и рубля :)

Ок, спасибо за исправление. Два (а не три) аргумента можно передать через регистры, если указать fastcall.

mv ★★★★★
()
Ответ на: комментарий от grey_a

> твоя версия не работает под 64 бита, т.к. является устаревшей

По-моему, его версия не работает под 64 бита потому, что херово написана изначально, а не потому, что устарела.

Испортилась, типа, ага...

mv ★★★★★
()
Ответ на: комментарий от mv

Собственно говоря, интерференция с SBCL произошла... Это там для x86 register-arg-count равен 3 :)

mv ★★★★★
()
Ответ на: комментарий от true_admin

> Привет, разработчик. Ну и весёлый у вас там код :). Скажи назавание продукта чтобы я случайно не купил. Шутка, не принимай близко к сердцу :).

grey_a зарегился только сегодня, и все его 2 поста -- в этой ветке.

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от mv

> Испортилась, типа, ага...

я же говорил что говно, а ты засахарилось, засахарилось..

dilmah ★★★★★
()
Ответ на: комментарий от Borman3000

> ну так а кто анонов в шею погнал - кто за этот геноцид ответит?=))))))))

ну не я во всяком случае, я и сейчас за анонимуса

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от true_admin

> При чём тут архитектура? Это от языка, реализации и стандартов зависит.

Топик же про C, да ещё и про Linux. Много ли этих самых calling conventions есть? Всякие stdcall и fastcall сразу мимо кассы, а изврат -mregparm=N требует пересборки всего, включая глибц, причём наверняка вручную и с большим напильником.

const86 ★★★★★
()
Ответ на: комментарий от grey_a

>т.к. является устаревшей, судя по всему аж прошлогодней, а то и раньше.
это твой мозг является устаревшим. выкинь его в мусорное ведро и работай дворником оставшуюся жизнь.
не, это же надо брать адрес аргумента функции и утверждать, что там полноценный массив.

xydo ★★
()
Ответ на: комментарий от true_admin

> тогда почему у топикстартера не получилось взять адрес аргумента ф-ии?

Потому что аргумент попал в регистр. Какой адрес у регистра? :)

mv ★★★★★
()
Ответ на: комментарий от true_admin

А ещё бывают машины, где стек растёт не вниз, а вверх.

mv ★★★★★
()
Ответ на: комментарий от mv

> Потому что аргумент попал в регистр. Какой адрес у регистра? :)

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

dilmah ★★★★★
()
Ответ на: комментарий от mv

ничего не понимаю. Как он туда попал если для того чтобы он туда попал нужно чтобы у gcc был особый ключик и весь дистр был собран с ни? Или, если я правильно понял, можно какой-то атрибут функции дать чтобы для её вызова аргументы делались.

true_admin ★★★★★
()
Ответ на: комментарий от mv

Эм, читать пункт 3.2.3 Parameter Passing? Там написано про то как это можно сделать а не как gcc сделает.

Но, кажись, я въехал. Если у топикстартера функция вызывается только один раз то она будет заинлайнена со всеми вытекающими последствиями.

true_admin ★★★★★
()
Ответ на: комментарий от true_admin

> Эм, читать пункт 3.2.3 Parameter Passing? Там написано про то как это можно сделать а не как gcc сделает. Эм, читать пункт 3.2.3 Parameter Passing? Там написано про то как это можно сделать а не как gcc сделает.

Нет.

void foo(int a, int b, int c, int d, int e, int f, int g, int h)
{
}

int main()
{
	foo(1, 2, 3, 4, 5, 6, 7, 8);
}

gcc -S:
        movl    $8, 8(%rsp)
        movl    $7, (%rsp)
        movl    $6, %r9d
        movl    $5, %r8d
        movl    $4, %ecx
        movl    $3, %edx
        movl    $2, %esi
        movl    $1, %edi
        call    foo

gcc -m32 -S:
        movl    $8, 28(%esp)
        movl    $7, 24(%esp)
        movl    $6, 20(%esp)
        movl    $5, 16(%esp)
        movl    $4, 12(%esp)
        movl    $3, 8(%esp)
        movl    $2, 4(%esp)
        movl    $1, (%esp)
        call    foo

mv ★★★★★
()
Ответ на: комментарий от true_admin

Катит. ABI на x86-64 предписывает первые 6 параметров функции передавать в регистрах. Это одна из причин, почему 32-битный x86 нужно давно закопать. На жирных процах вообще 32-128 регистров...

mv ★★★★★
()
Ответ на: комментарий от mv

> На жирных процах вообще 32-128 регистров...

Кстати, да. Почему-то разработчики x86-64 опять пожадничали, 16 всего сделали :( Но и то хорошо. Кстати, ещё 8 параметров в XMM-регистры можно упихать. Посмотришь на всё это - и невольно хочется передавать всю инфу через параметры функций, не группируя в структуры :)

const86 ★★★★★
()
Ответ на: комментарий от mv

Всё, теперь всё понял, спасибо. Нашёл табличку Figure 3.4: Register Usage

true_admin ★★★★★
()
Ответ на: комментарий от const86

вот этот вопрос меня уже очень давно мучает. Почему не хотят запихнуть десяток-другой регистров? Можно ли использовать для этого, скажем, регистры mmx или sse(сорри за тупой вопрос :))?

true_admin ★★★★★
()
Ответ на: комментарий от true_admin

Наверное, потому что opcodes пытались более-менее сохранить. Какой-то legacy бит принесли в жертву в два раза большему кол-ву регистров. Если менять опкоды, то проще вообще новую архитектуру сделать. x86 - это тот ещё п-ц.

Собственно, линуксоидам, которые на онеме не онанируют и флеш не смотрят, давно уже можно брать машинки на ARM... Емакс там такой же.

mv ★★★★★
()
Ответ на: комментарий от mv

>которые на онеме не онанируют

Эмм.. виноват, а в чем проблем онанировать на онеме с ARM?

>давно уже можно брать машинки на ARM...

И где такую взять?

Waterlaz ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.