printf()函数导致segfault

时间:2015-10-09 21:37:40

标签: c segmentation-fault printf

编译时,此代码允许我使用正确的IP地址作为程序参数连接到服务器。到目前为止,连接很好并且数据被发送到服务器,但是当我尝试使用recv()函数尝试以非阻塞模式收集数据时,我收到了分段错误。它总是出现在“接收数据......”行之后。

正如您所看到的,我为操作保留了5000字节的堆栈内存,而我正在测试只尝试读取一个字节而没有成功。 recv()不能用于堆栈内存吗?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>

extern errno;

struct sockaddr_in a;
struct timeval tv;
fd_set wready;

long conntoserver(const char* ip,const char* data){
    memset((char*)&a,0,sizeof(a));
    if (inet_aton(ip,a.sin_addr.s_addr) == 0){printf("Can't set address\n");return -1;}
    long s=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);if (s < 0){printf("Can't make socket\n");return -1;}
    tv.tv_sec=1;tv.tv_usec=0;FD_ZERO(&wready);FD_SET(s,&wready);
            //start non-blocking mode
    if (fcntl(s,F_SETFL,O_NONBLOCK) < 0){printf("Can't make socket non-blocking\n");close(s);return -1;}
    a.sin_family=AF_INET;a.sin_port=htons(80);long ret=connect(s,(struct sockaddr*)&a,sizeof(a));
    if (ret < 0 && errno != EINPROGRESS){printf("Can't connect to IP. %s\n",strerror(errno));close(s);return -1;}
    if (errno == EINPROGRESS){
    printf("connection in progress...\n");
    ret=select(s+1,NULL,&wready,NULL,&tv);
    if (ret < 0){printf("select() error. %s\n",strerror(errno));close(s);return -1;}
    if (ret==0){printf("select() timeout. %s\n",strerror(errno));close(s);return -1;}
    }
    unsigned long sz=strlen(data);
    ssize_t ns=send(s,data,sz,0);
    if (ns==sz){return s;}else{return -1;}
}

int main(int argc,char* argv[]){
    if (argc < 2){printf("Format: %s < IP to connect to >\n",argv[0]);return -1;}
    long s=conntoserver(argv[1],"GET / HTTP/1.1\nHost: example.com\n\n");
    if (s < 0){printf("Error making server request. %s\n",strerror(errno));close(s);return -1;}
    printf("receiving data...\n");
    char b[5001];
    ssize_t br=recv(s,b,1,0);
    printf("br=%s\n",br);
    close(s);
    return 0;
}

2 个答案:

答案 0 :(得分:0)

printf("br=%s\n",br);

应该是:

printf("br=%ld\n",br);
BTW - 我不得不修复一些问题来编译这段代码。您应该始终注意编译器警告。

答案 1 :(得分:0)

除了@keithmo指出的错误之外,你还有一个错误:

    if (inet_aton(ip,a.sin_addr.s_addr) == 0){printf("Can't set address\n");return -1;}

inet_aton()的第二个参数应该是struct in_addr指针,但是您传递的值为uint32_t。实际上,该值初始化为零,因此结果很可能(但不确定)等同于传递NULL指针。无论哪种方式,这都会产生不确定的行为,如果没有表现为段错误,我会感到惊讶。即使程序运行过程,您编写的调用也无法产生(显然)在变量a中初始化地址所需的效果。

你想要的是

    if (inet_aton(ip, &a.sin_addr) == 0) {
        printf("Can't set address\n");
        return -1;
    }

为了善良,免费使用空格和换行符。它们大大提高了代码的易读性。如果你做空,我可以借给你一些。