使用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
相关产品推荐
相关产品推荐

