Как бросить sockaddr_storage и постараться не нарушать строго искажающие правила

using System.Diagnostics;

Process.Start("http://www.google.com/");

Этот подход работал на меня, но я мог пропускать что-то важное.

24
задан sinoth 15 September 2009 в 21:18
поделиться

2 ответа

Я обычно делаю это, чтобы заставить GCC поступать правильно с помощью выбора типов , что явно разрешено с объединениями:


/*! Multi-family socket end-point address. */
typedef union address
{
    struct sockaddr sa;
    struct sockaddr_in sa_in;
    struct sockaddr_in6 sa_in6;
    struct sockaddr_storage sa_stor;
}
address_t;
21
ответ дан 29 November 2019 в 00:20
поделиться

Проблема не имеет ничего общего с вызовом функции. Скорее, это с ((struct sockaddr_in*)sa)->sin_addr. Проблема в том, что sa является указателем одного типа, но вы бросаете его на указатель другого типа, а затем разыменовываете его. Это нарушает правило под названием «строгое сглаживание», которое гласит, что переменные разных типов никогда не могут псевдонимиться. В вашем случае псевдоним для другого типа — это именно то, что вы хотите сделать.

Простым решением является отключение этой оптимизации, которая позволяет сглаживать таким образом. На GCC флаг -fno-strict-aliasing.

Лучшим решением будет использование союза, как упоминал Николай.

void *get_in_addr(struct sockaddr *sa)
{
    union {
        struct sockaddr     *sa;
        struct sockaddr_in  *sa_in;
        struct sockaddr_in6 *sa_in6;
    } u;
    u.sa = sa;
    if (sa->sa_family == AF_INET)
        return &(u.sa_in->sin_addr);
    else
        return &(u.sa_in6->sin6_addr);
}

Тем не менее,На самом деле я не могу заставить GCC дать мне предупреждение при использовании вашего исходного кода, поэтому я не уверен, что это вам что-то покупает.

-1
ответ дан 29 November 2019 в 00:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: