LINUX.ORG.RU

UB или нет?

 ,


0

3

Привет. Я хочу присвоить указателю на функцию адрес следующей open() через dlsym и RTLD_NEXT. При сборке тестового примера с

cc -std=c17 -pedantic -Wall -Wextra -ldl test.c
компилятор жалуется на

ISO C forbids assignment between function pointer and ‘void *’ [-Wpedantic]

dlsym() возвращает data pointer, а присваиваем function pointer. Но, если взять пример здесь, то предупреждения компилятора при присваивании b не будет. Вопрос: пример с b это теперь не UB? Если UB, то почему пропало предупреждение? Если я не ошибаюсь, то void ** - указатель на data pointer.

#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>

int main(void)
{
        static void (*a)(void);
        static void (*b)(void);

        a = dlsym(RTLD_NEXT, "open");
        *(void **)(&b) = dlsym(RTLD_NEXT, "open");

        if (a == b)
                printf("a == b""\n");

        return 0;
}

то предупреждения компилятора при присваивании b не будет.

Так предупреждение же на присваивание a выдаётся.

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

a - это очевидный способ с предупреждением, а b - из opengroup.org и без предупреждения.
Меня интересует, является ли UB способ с b.

Arlecchino ★★ ()
Последнее исправление: Arlecchino (всего исправлений: 1)
Ответ на: комментарий от anonymous

На всякий случай, оставлю ещё цитату из POSIX описания dlsym:

Note that conversion from a void * pointer to a function pointer as in:

fptr = (int (*)(int))dlsym(handle, "my_function");

is not defined by the ISO C standard. This standard requires this conversion to work correctly on conforming implementations.

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

dlfunc() из FreeBSD не приводит к предупреждению:

#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>

/* FreeBSD dlfcn.h */
struct __dlfunc_arg {
        int __dlfunc_dummy;
};
typedef void (*dlfunc_t)(struct __dlfunc_arg);
dlfunc_t dlfunc(void *restrict handle, void *restrict symbol);

/* FreeBSD dlfunc.c */
dlfunc_t dlfunc(void *restrict handle, void *restrict symbol) {
        union {
                void *d;
                dlfunc_t f;
        } rv;
        rv.d = dlsym(handle, symbol);
        return rv.f;
}

int main(void)
{
        static void (*a)(void);
        static void (*b)(void);

        a = (void (*)(void))dlfunc(RTLD_NEXT, "open");
        *(void **)(&b) = dlsym(RTLD_NEXT, "open");

        if (a == b)
                printf("a == b""\n");

        return 0;
}
Arlecchino ★★ ()

В сишном стандарте указатели на данные и указатели на код могут быть разного размера. В но в каком-то из POSIX — нет.

deadplace ()
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.