当前位置:  开发笔记 > 编程语言 > 正文

TCP通信中的分段错误

如何解决《TCP通信中的分段错误》经验,为你挑选了2个好方法。

我在以下C代码中遇到了分段错误:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define PORT  6667
#define MAXDATASIZE 1024

int bot_connect(char *hostname);

int bot_connect(char *hostname) {

  int sockfd, numbytes, s;
  char buf[MAXDATASIZE];
  struct addrinfo hints, *servinfo, *p;
  int rv;
  char m[1024];
  char *message;
  char *nick = "Goo";
  char *ident = "Goo";
  char *realname = "Goo";

  memset(&hints,0,sizeof hints);
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_STREAM;

  rv = getaddrinfo(hostname, PORT, &hints, &servinfo);

  if (rv != 0) {
    fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
    return 1;
  }

  for (p = servinfo; p != NULL; p = p->ai_next) {
    sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
    if (sockfd == -1) {
      perror("Client: socket");
      continue;
    }

    if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
      close(sockfd);
      perror("Client: connect");
      continue;
    }

    break;
  }

  if (p == NULL) {
    fprintf(stderr, "Client: failed to connect \n");
    return 2;
  }

  freeaddrinfo(servinfo);

  strcat(m, "NICK ");
  strcat(m, nick);
  message = m;
  s = send(sockfd, message, strlen(message), 0);

  strcat(m, "USER ");
  strcat(m, ident);
  strcat(m, " * * :");
  strcat(m, realname);
  message = m;
  s = send(sockfd, message, strlen(message), 0);

  message = "JOIN #C&T";
  s = send(sockfd, message, strlen(message), 0);

  close(sockfd);
}

我知道你试图用你不允许做的内存做一些分段错误,比如改变只读内存,但据我所知,这个程序不会这样做.有没有人知道细分故障的来源?



1> Graeme Perro..:

strcat( m, "NICK" );在初始化m之前打电话.在strcat之前,尝试m[0] = '\0';或者memset( m, 0, sizeof( m ) );,或者先strcat改为strcpy

此外,在套接字上发送NICK线后,strcat再次调用,这会将USER线附加到NICK线.再说一遍,你应该把第一个更改strcatstrcpy



2> Tyler McHenr..:

格雷姆对"什么"是正确的,所以这里是"为什么",以防你不熟悉.在C中,字符串被定义为由空字符'\ 0'终止的一系列字符.字符串具有终止字符的原因是代码可以找出字符串逻辑结束的位置.即使你声明一个这样的字符串:

 char m[1024];

在C中没有办法给出m给出的代码可以找出它分配了1024个字节,更不用说弄清楚这些字节有多少是有意义的,而没有一个空字符划分有意义字节的结尾.

strcat是一个可以处理两个C字符串的函数,因此它希望它的两个参数都符合规范,即有一个空字节标记有意义输入的结束.如果m未初始化,则其内容是随机的,因此空字节可以是任何位置,或者根本不存在空字节.为了连接,strcat将查看第一个参数的字符,试图找到标记字符串结尾的空字节.如果偶然,没有空字节未初始化数组中存在,它会很乐意继续寻找过去的字符串的末尾,成可以对应于其它变量的任意存储位置,或内部堆栈信息等

当strcat最终找到一个空字节时,它会愉快地写出从该位置开始的第二个参数的内容,如果该位置超过m的结尾,它将覆盖其他一些变量或其他信息.如果它是一个分配给其他变量的内存地址,那么问题可能是沉默的,很难找到.幸运的是,在你的情况下,它是一个不应写入的位置,所以你的程序崩溃了一个明显的错误.

这也提示你应该使用strncat而不是strcat.strncat允许您指定要创建的字符串的最大长度.我之前注意到strcat无法确定m是否有1024个字节分配给它,所以如果你试图将m与m长于1023个字符的东西连接起来,你最终会遇到相同的内存覆盖问题.strncat接受第三个参数,该参数指定结果字符串的最大长度,并且具有返回代码,该返回代码将指示是否由于达到此长度而截断了连接.

推荐阅读
罗文彬2502852027
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有