You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Winsock开发SMTP C程序时触发段错误求助

Winsock重构后段错误的问题分析与修复

核心问题:空指针解引用导致段错误

在makeSocket函数中,你传入的result和ptr是值传递的结构体指针,而非指针的指针。这意味着函数内部对ptr = result的赋值只会修改函数内的局部变量,不会同步到main函数中的ptr变量。当main调用connSocket时,ptr仍然是初始的NULL,此时访问ptr->ai_addr就会触发空指针解引用,直接导致段错误。

修复步骤

1. 修改makeSocket的参数传递方式

将result和ptr改为指针的指针,让函数能修改main中的变量:

  • 函数声明改为:
    int makeSocket(int *, struct addrinfo *, struct addrinfo **, struct addrinfo **, SOCKET *);
    
  • main中调用时传地址:
    makeSocket(&iResult, &hints, &result, &ptr, &ConnectSocket);
    
  • 函数内部逻辑修改:
    int makeSocket(int *iResult, struct addrinfo *hints, struct addrinfo **result, struct addrinfo **ptr, SOCKET *ConnectSocket){
        // Resolve the server address and port
        *iResult = getaddrinfo("52.97.26.134", DEFAULT_PORT, hints, result);
        if (*iResult != 0) {
            printf("getaddrinfo failed: %d\n", *iResult);
            WSACleanup();
            return 1;
        }
    
        // Attempt to connect to the first address returned by
        // the call to getaddrinfo
        *ptr = *result;
    
        // Create a SOCKET for connecting to server
        *ConnectSocket = socket((*ptr)->ai_family, (*ptr)->ai_socktype, (*ptr)->ai_protocol);
    
        if (*ConnectSocket == INVALID_SOCKET) {
            printf("Error at socket(): %d\n", WSAGetLastError());
            freeaddrinfo(*result);
            WSACleanup();
            return 1;
        }
        return 0;
    }
    

2. 修复clientReceive中的判断错误

函数中直接用iResult比较,而不是解引用后的*iResult,会导致逻辑错误:

int clientReceive(int *iResult, SOCKET *ConnectSocket, char *out){
    *iResult = recv(*ConnectSocket, out, 200, 0);
    if (*iResult > 0) {
        printf("Bytes received: %d\n", *iResult);
        return 0;
    } else if (*iResult == 0) {
        printf("Connection closed\n");
        return 1;
    } else {
        printf("recv failed: %d\n", WSAGetLastError());
        return 2;
    }

    return -1;
}

3. 避免重复调用WSACleanup

closeSocketListener和closeSocket都调用了WSACleanup,但该函数只需要调用一次,建议只在closeSocket中保留:

int closeSocketListener(int *iResult, SOCKET *ConnectSocket){
    // shutdown the send half of the connection since no more data will be sent
    *iResult = shutdown(*ConnectSocket, SD_SEND);
    if (*iResult == SOCKET_ERROR) {
        printf("shutdown failed: %d\n", WSAGetLastError());
        closesocket(*ConnectSocket);
        return 1;
    }
    return 0;
}

修复后流程说明

修改后,makeSocket会将getaddrinfo返回的地址链表头指针同步到main的result和ptr中,connSocket就能正确访问ptr指向的地址信息,彻底避免空指针错误。

内容的提问来源于stack exchange,提问作者fpp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 12:51:36