LINUX.ORG.RU

GCC: приведение типа отменяет квалификаторы указуемого типа


0

0

GCC генерирует предупреждение, описанное в subj для строки с execv. Хочется правильно его избежать (т.е. не отключая предупреждения). Если argsarray переопределить как char *, и убрать преобразование типа в execv, тогда ругается на строку с циклом for, т.к. program является const char *. Есть какой-нибудь красивый способ избежать предупреждений в таком коде:

void MYsystem(const char *program, ...) {
pid_t childpid;
int tmp = 0;
va_list args;
const char *argsarray[MAXARGS];

childpid = fork();
if (childpid == 0) {
va_start(args, program);

for (argsarray[0] = program; (argsarray[tmp] = va_arg(args, char *)) != NULL; tmp++);

execv(program, (char * const *)argsarray);

★★★★★

Если argsarray переопределить как char *, и убрать преобразование типа в execv, тогда ругается на строку с циклом for, т.к. program является const char *: "assignment discards qualifiers from pointer target type".

Если для вышеизложенного в цикле for добавить к program (char *), то: "приведение типа отменяет квалификаторы указуемого типа" :-(

Если этого не избежать, то подскажите, какой код лучше оставить (с точки зрения безопасности кода)? Моё мнение - из последнего абзаца.

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

+1. (gcc-4.1.1) Что gcc, что g++ - компилирует чисто.

slav ★★
()

execv в качестве argv требует char *const argv[], т.е. массив константных указателей на символы. Т.е. в общем случае он может менять содержимое строк, лежащих в этом массиве.

argsarray у тебя - массив указателей на константные строки. Которые, естественно, менять нельзя.

Резюме: тебе нужно аллокировать память для всех cтрок, лежащих в argv. Ну или, если это возможно, передавать в функцию неконстантные строки.

execve
()

Тех флагов мало, чтобы "получить" по полной соберите с:
-std=c99 \
-Wall -W -Wredundant-decls -Wnested-externs -Wstrict-prototypes \
-Wmissing-prototypes -Wpointer-arith -Winline -Wcast-qual \
-Wreturn-type -Wswitch -Wshadow -Wcast-align -Wuninitialized \
-Wchar-subscripts -Wuninitialized -Wbad-function-cast -Wwrite-strings

У меня всего 3 warning с такими флагами на весь проект, первые 2 - по поводу putenv (но это проблема заголовочных файлов linux-а, на HP-UX всё ок), а вот последний - subj, и как исправить не знаю. От остальных избавился, хотя HP-UX cc немного больше генерит, чем GNU cc ;-)

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

> Резюме: тебе нужно аллокировать память для всех cтрок, лежащих в argv.

Как то не оптимально :-\ Указатели же пришли в функцию и массив argsarray осталось только заполнить нужными :-\ Эта функция достаточно часто вызывается.

> Ну или, если это возможно, передавать в функцию неконстантные строки.

Тогда с теми флагами gcc ругается по всему коду, где бы ни вызывалась эта функция подобным образом: MYsystem("/bin/ls", "/bin/ls", "-l", NULL);

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

> Как то не оптимально :-\ Указатели же пришли в функцию и массив argsarray осталось только заполнить нужными :-\ Эта функция достаточно часто вызывается.

В функцию пришли указатели на константные строки. А execv хочет указатели на изменяемые строки. Первое ко второму корректно привести нельзя. Только создать новый буфер и скопировать в него из исходной строки.

Мало того, если это действительно константная строка, то при попытке записать в неё ты запросто можешь получить SIGSEGV.

> Тогда с теми флагами gcc ругается по всему коду, где бы ни вызывалась эта функция подобным образом: MYsystem("/bin/ls", "/bin/ls", "-l", NULL);

Тем более.

Представь себе, что вызываемая тобой программа захочет вдруг что-то записать в argv[0] (который "/bin/ls"). SIGSEGV гарантирован.

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

$ uname -a
Linux XXXXXXXX 2.6.18-4-686 #1 SMP Wed Feb 21 16:06:54 UTC 2007 i686 GNU/Linux

$ gcc --version
gcc (GCC) 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ cat <<EOT >1.c
int
main()
{
        ((char *)"1234")[1] = 'q';
        return 0;
}
EOT

$ cc -W -Wall -pedantic -std=c99 -O0 1.c -o 1

$ ./1
[1]    12267 segmentation fault (core dumped)  ./1

Вобщем ты извини, но я на этом, пожалуй, закончу.

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

> Представь себе, что вызываемая тобой программа захочет вдруг что-то записать в argv[0] (который "/bin/ls"). SIGSEGV гарантирован.

Я вот этот случай и воспроизвел с функцией из первого сообщения, даже ps посмотрел, что она имя поменяла.

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

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

Большое спасибо. Так и сделал, malloc+strcpy, причем только вместо argsarray[0] = program.

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