【问题标题】:inet_ntoa() segmentation fault on OSXOSX 上的 inet_ntoa() 分段错误
【发布时间】:2013-06-17 03:41:10
【问题描述】:

我遇到了 inet_ntoa 在 OSX 上导致分段错误的问题, 而这在 Linux 上不会发生。

我的测试代码如下。

// sample.c
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
//#include <arpa/inet.h>  // adding this line prevents the segfault

int main() {
    struct sockaddr_in addr;
    struct sockaddr_in client;

    int sock0 = socket(AF_INET, SOCK_STREAM, 0);
    addr.sin_family = AF_INET;
    addr.sin_port = htons(12345);
    addr.sin_addr.s_addr = INADDR_ANY;

    bind(sock0, (struct sockaddr *)&addr, sizeof(addr));
    listen(sock0, 5);

    while (1) {
        int len = sizeof(client);
        int sock = accept(sock0, (struct sockaddr *)&client, (socklen_t *)&len);
        printf("accepted connection from %s, port=%d\n",
               inet_ntoa(client.sin_addr), ntohs(client.sin_port));
        send(sock, "HELLO", 5, 0);
        close(sock);
    }

    close(sock0);

    return 0;
}

我搜索了一段时间,发现a solution 添加了一个包含“arpa/inet.h”。 我确认 inet_ntoa 肯定是在 inet.h 中声明的,我确信这是正确的方式。

但我不明白为什么没有它这段代码就不能工作。当我在没有包含行的情况下构建和链接此代码时会发生什么?

我知道构建此代码会显示警告“函数的隐式声明”,但不会发生链接错误。 我认为,这意味着链接器以某种方式找到了 inet_ntoa 的实现。 这是错的吗?

谢谢!非常感谢任何建议。

【问题讨论】:

    标签: c macos sockets gcc


    【解决方案1】:

    我猜你的 OSX 系统是 64 位的,而你的 Linux 系统是 32 位的。假定未声明的函数返回一个整数。如果 64 位指针衰减为作为指针解引用的 32 位整数,您可能会遇到分段错误。

    【讨论】:

      【解决方案2】:

      C 允许隐式声明函数 (Implicit function declarations in C)。这就是为什么您没有收到编译器错误的原因。另外 inet_ntoa 在 glibc 中,默认情况下由 gcc 链接,因此链接器会找到函数的定义,因此您不会收到链接器错误。发生段错误是因为 1) C 假设,因为它是隐式声明的,所以函数返回一个 int 和 2) 在 Mac 上 glibc 中的 inet_ntoa 正在返回一个 64 位指针,该指针被转换为 32 位值并丢失信息。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-09-17
        • 1970-01-01
        • 2012-04-24
        • 2012-05-19
        • 1970-01-01
        • 1970-01-01
        • 2015-01-25
        • 1970-01-01
        相关资源
        最近更新 更多