inet_ntop 函数崩溃问题

        今天在看TCP/IP 协议时看到一段代码,于是就拷贝下来自己编译运行一下,结果出现一个segmentation fault,这是一个奇怪的现象,奇怪在哪里呢?请往下看。

/* server.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define MAXLINE 80
#define SERV_PORT 8000

int main(void)
{
	struct sockaddr_in servaddr, cliaddr;
	socklen_t cliaddr_len;
	int listenfd, connfd;
	char buf[MAXLINE];
	char str[INET_ADDRSTRLEN];
	int i, n;

	listenfd = socket(AF_INET, SOCK_STREAM, 0);

	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	servaddr.sin_port = htons(SERV_PORT);
    
	bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));

	listen(listenfd, 20);

	printf("Accepting connections ...\n");
	while (1) {
		cliaddr_len = sizeof(cliaddr);
		connfd = accept(listenfd, 
				(struct sockaddr *)&cliaddr, &cliaddr_len);
	  
		n = read(connfd, buf, MAXLINE);
		printf("received from %s at PORT %d\n",
		       inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)),
		       ntohs(cliaddr.sin_port));
    
		for (i = 0; i < n; i++)
			buf[i] = toupper(buf[i]);
		write(connfd, buf, n);
		close(connfd);
	}
}

这是一个服务端代码,编译没有问题,这段代码主要工作就是:接收到客户端的字符后,转换成大写再发给客户端。客户端的代码也帖一下:

/* client.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define MAXLINE 80
#define SERV_PORT 8000

int main(int argc, char *argv[])
{
	struct sockaddr_in servaddr;
	char buf[MAXLINE];
	int sockfd, n;
	char *str;
    
	if (argc != 2) {
		fputs("usage: ./client message\n", stderr);
		exit(1);
	}
	str = argv[1];
    
	sockfd = socket(AF_INET, SOCK_STREAM, 0);

	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);
	servaddr.sin_port = htons(SERV_PORT);
    
	connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));

	write(sockfd, str, strlen(str));

	n = read(sockfd, buf, MAXLINE);
	printf("Response %u charactor from server: %s\n", n, buf);

	close(sockfd);
	return 0;
}

Makefile



COMPILE_DIR = compile
BIN_DIR = bin


# 编译arm版本
#CROSS = arm-himix200-linux-
CC = $(CROSS)gcc 
CFLAGS = -W -g

LIB = -lpthread
# SRCS = $(wildcard *.cpp)
# SRCS = $(shell ls -t | grep "\.c$$" | head -1)
SRCS = server.c client.c
OBJS = $(patsubst %.c, $(COMPILE_DIR)/%.o, $(SRCS))
DEP = $(patsubst %.c, $(COMPILE_DIR)/%.c.d, $(SRCS))


$(shell if [ ! -d $(COMPILE_DIR) ]; then mkdir $(COMPILE_DIR); fi)
$(shell if [ ! -d $(BIN_DIR) ]; then mkdir $(BIN_DIR); fi)


TARGET_SERVER=$(BIN_DIR)/server
TARGET_CLIENT=$(BIN_DIR)/client


all: $(TARGET_SERVER) $(TARGET_CLIENT)


$(TARGET_SERVER): server.c
	$(CC) $(CFLAGS) $< -o $@ $(LIB)

$(TARGET_CLIENT): client.c
	$(CC) $(CFLAGS) $< -o $@ $(LIB)


$(COMPILE_DIR)/%.o: %.c $(COMPILE_DIR)/%.c.d
	$(CC) $(CFLAGS) -c $< -o $@

$(COMPILE_DIR)/%.c.d: %.c
	$(CC) $(CFLAGS) -MM -E -c $< -o $@
	@sed 's/.*\.o/$(subst /,\/,$(dir $@))&/g' $@ > $@.tmp
	@mv $@.tmp $@


.PHONY: clean
clean:
	rm -rf $(COMPILE_DIR) $(BIN_DIR)

用 gdb 跟踪调试,segmentation fault 出现在库函数 printf() 里:

看这参数也没问题啊,而且我还 man 了一下 inet_ntop 的用法,如下:

 除非 inet_ntop 返回 NULL,用 %s 打印的话可能会有问题,所以在gdb里我执行了一下 inet_ntop 函数,如:

 这里不明白为什么返回值是 int 类型呢?而 man 出来的inet_ntop 函数是返回 const char * 类型的啊。而且当我把代码改成这样时,把 inet_ntop 提出来放到 if 里:

	while (1) {
		cliaddr_len = sizeof(cliaddr);
		connfd = accept(listenfd, 
				(struct sockaddr *)&cliaddr, &cliaddr_len);
	  
		n = read(connfd, buf, MAXLINE);
		if(inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)) != NULL) {
			printf("received from %s at PORT %d\n", str, ntohs(cliaddr.sin_port));			
		}

    
		for (i = 0; i < n; i++)
			buf[i] = toupper(buf[i]);
		write(connfd, buf, n);
		close(connfd);
	}

得到了一条编译警告:

 是不是很奇怪?这里警告我比较了指针类型和int类型,难道这个函数原型用的是另外什么版本的吗?然后我发现,代码里没有包含头文件:<arpa/inet.h>,man 的时候看到的。于是我把这个头文件加上

/* server.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

再编译就没问题了,难道不包含声明函数原型的头文件,编译器就默认其返回值是 int 吗?就算没有包含原型声明,但在运行时链接的动态库里的函数,应该也是没问题才对啊,那为什么不包含头文件运行起来会出现段错误呢?而加了头文件后,运行则是正常的:

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱跑步的码农

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值