كيف للادلاء sockaddr_storage وتجنب كسر القواعد الصارمة التعرج

StackOverflow https://stackoverflow.com/questions/1429645

سؤال

وأنا باستخدام دليل Beej لشبكة وجاء عبر قضية التعرج. وتقترح وظيفة للعودة إما عناوين IPv4 أو عنوان IPv6 لبنية معينة:

1  void *get_in_addr( struct sockaddr *sa )
2  {
3      if (sa->sa_family == AF_INET)
4        return &(((struct sockaddr_in*)sa)->sin_addr);
5      else
6        return &(((struct sockaddr_in6*)sa)->sin6_addr);
7  }

وهذا يؤدي إلى دول مجلس التعاون الخليجي بصق خطأ الصارم التعرج لعلى سا على خط 3. كما أفهمها، فمن لأنني استدعاء هذه الدالة كما يلي:

struct sockaddr_storage their_addr;
...
inet_ntop(their_addr.ss_family,
          get_in_addr((struct sockaddr *)&their_addr),
          connection_name,
          sizeof connection_name);

وأنا التخمين التعرج له علاقة مع حقيقة أن المتغير their_addr من نوع sockaddr_storage ومؤشر آخر على اختلاف نقاط النوع لنفس الذاكرة.

وهو أفضل وسيلة للالتفاف حول هذا sockaddr_storage الخلاف، sockaddr_in، وsockaddr_in6 إلى اتحاد؟ يبدو مثل هذا الإقليم يجب أن ترتديه بشكل جيد في مجال الشبكات، أنا فقط لا يمكن العثور على أي أمثلة جيدة مع أفضل الممارسات.

وأيضا، إذا كان أي شخص يمكن أن يفسر بالضبط أين تأخذ هذه القضية التعرجات مكان، فما استقاموا لكم فاستقيموا نقدر ذلك كثيرا.

هل كانت مفيدة؟

المحلول

وأنا أميل إلى القيام بذلك للحصول على دول مجلس التعاون الخليجي فعل الشيء الصحيح مع <لأ href = "http://gcc.gnu.org/onlinedocs/gcc-4.4.1/gcc/Optimize-Options.html#Type_002dpunning" يختلط = "noreferrer"> نوع المجانسة ، الذي يسمح صراحة مع النقابات:


/*! 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;

نصائح أخرى

<اقتباس فقرة>   

وأنا أميل إلى القيام بذلك للحصول على دول مجلس التعاون الخليجي فعل الشيء الصحيح مع نوع المجانسه، الذي يسمح صراحة مع النقابات

وأنا متأكد من هذا (سوء) استخدام الاتحاد سوف <م> لا العمل (أو فقط عن طريق الصدفة) مع دول مجلس التعاون الخليجي:

short type_pun2 (int i, int *pi, short *ps) {
    *pi = i;
    return *ps;
}

union U {
    int i;
    short s;
};

short type_pun (int i) {
    U u;
    return type_pun2 (i, &u.i, &u.s);
}

والطريقة الصحيحة لذلك هي مع memcpy، وليس union.

وكان لي مؤخرا تحذيرا مماثلا الاسم المستعار على النظام HPUX عند محاولة كتابة التعليمات البرمجية للحصول على عنوان MAC للجهاز

وو&(((struct sockaddr_in *)addr)->sin_addr) يشكو قواعد صارمة التعرج

وهذا هو رمز في بعض السياق

 char ip[INET6_ADDRSTRLEN] = {0};
 strucut sockaddr *addr

 ...
 get addr from ioctl(socket,SOCGIFCONF...) call
 ...
 inet_ntop(AF_INET, &(((struct sockaddr_in *)addr)->sin_addr),ip,sizeof ip);

ولقد تغلبت على التحذير التعرج طريق القيام بما يلي

struct sockaddr_in sin;
memcpy(&sin,addr,sizeof(struct sockaddr));
inet_ntop(AF_INET, &sin.sin_addr,ip,sizeof ip);

وبينما هذا يحتمل أن تكون خطرة أضفت الأسطر التالية قبل أن

 static_assert(sizeof(sockaddr)==sizeof(sockaddr_in));

ولست متأكدا إذا كان هذا هو أن شيئا تعتبر ممارسة سيئة، لكنه يعمل وكان عبر منصة لأخرى النكهات نيكس * والمجمعين

وهذه القضية لا علاقة لها الدعوة إلى وظيفة لا شيء. بدلا من ذلك، انها مع ((struct sockaddr_in*)sa)->sin_addr. والمشكلة هي أن sa هو مؤشر من نوع واحد، ولكن كنت الصب إلى مؤشر من نوع مختلف ومن ثم dereferencing ذلك. هذا يكسر قاعدة تسمى "التعرج صارم"، التي تقول إن المتغيرات من أنواع مختلفة لا يمكن أبدا أن الاسم المستعار. في قضيتك، التعرج إلى نوع مختلف هو بالضبط ما تريد القيام به.

والحل بسيط هو إيقاف هذا التحسين، والذي يسمح التعرج بهذه الطريقة. على دول مجلس التعاون الخليجي، والعلم هو -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);
}

وقال ذلك، لا أستطيع في الواقع الحصول على دول مجلس التعاون الخليجي أن تعطيني تحذير عند استخدام التعليمات البرمجية الأصلية الخاصة بك، لذلك أنا لست متأكدا مما إذا كان هذا يشتري لك شيئا.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top