Сходство по структуре и внутреннему расположению элементов - PullRequest
0 голосов
/ 21 сентября 2018

Допустим, у нас есть следующая структура (где T и U - любой из основных типов данных, таких как int, long, char и т. Д.)

struct S1 {
   T t1;
   U u1;
};

и другая структура

struct S2 {
   T t2;
   U u2;
};

Теперь я выделяю

struct S1* s1 = malloc(sizeof(*s1))

И с container_of, определенным как

#define container_of(ptr, type, member) ({ \
    const typeof( ((type *)0)->member ) \
    *__mptr = (ptr);
    (type *)( (char *)__mptr - offsetof(type,member) );})

, если я перейду к T* x, следующее может быть сделано

struct S2* s2 = container_of(x, struct S2, t2)
//Here s2->u2 is the same value as that of s1->u1

Теперь мой запрос предполагает, что такие операции происходят не замечая друг друга (например, в разных библиотеках), это может привести к странным изменениям значений.

Контекст:

У меня есть свой собственный код с S1, но когда я передаю t1 другому библиотечному коду, он имеет другую подобную структуру S2 и в конечном итоге тоже изменяет значение u1.Есть ли способ защититься от таких непреднамеренных случаев использования?Также, скажем, на каждом конце интерфейса у нас есть указатель T* x, но и разработчик интерфейса, и клиент интерфейса для их использования сохраняют его как часть структур S1 и S2.В этом случае также может возникнуть такая же ситуация, когда в основном код сервера будет неизменным.Как мы решаем эту проблему в этих случаях?

Реальный пример из ядра Kernel V4L2 здесь

static void __fill_v4l2_buffer(struct vb2_buffer *vb, void *pb)
{
    struct v4l2_buffer *b = pb;
    struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
    :
    :
    b->flags = vbuf->flags;

Теперь я выделил структуру следующим образом:

my_v4l2_driver_video_buf{
    struct vb2_buffer vb;
    dma_addr_t addr;
}

и вот определение vb2_v4l2_buffer

struct vb2_v4l2_buffer {
    struct vb2_buffer   vb2_buf;    
    __u32           flags;
    __u32           field;
    struct timeval      timestamp;
    struct v4l2_timecode    timecode;
    __u32           sequence;
};

Примечание: dma_addr_t тоже был 32-битным

А потом я передал указатель наvb до v4l2 рамки.Он изменил флаги в функции __fill_v4l2_buffer, и я получил флаги v4l2_buffer* b, равные dma_addr_t addr моей структуры

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...