【问题标题】:C program is randomly changing value of int [closed]C程序正在随机改变int的值[关闭]
【发布时间】:2016-08-04 04:31:10
【问题描述】:

我真的很困惑。我有一个 C 服务器,它运行良好,但后来我添加了一些代码,我认为它运行良好,直到我的 c 程序随机开始将 int 的值更改为负值。

基本上我让我的服务器输出发送的总字节数,在传输过程中,总是在 2100000000 字节左右,总字节数变为负数。这是我的输出文件的示例。如果您查看我的代码,该值不能只是变成负数。所以我怀疑这是更奇怪的事情。

"345000","1470253912","59203","5592","2069901108"
"348000","1470253912","475539","4194","2092449162"
"351000","1470253912","830291","2796","2112043464"
"354000","1470253913","243217","1398","2133985176"
"357000","1470253913","708686","13980","-2135434834"
"360000","1470253914","173646","9786","-2109094024"
"363000","1470253914","514938","6990","-2089413400" 

无论如何,我添加的东西,我注释掉了,我仍然遇到同样的错误。仅供参考,它已在我的代码中的“添加新内容”标签下注释掉。 (因为这篇文章我添加了它:Terminating C program on command line, but make sure writer is finished writing )

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <errno.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <netdb.h>
    #include <arpa/inet.h>
    #include <sys/wait.h>
    #include <signal.h>
    #include <sys/time.h>



int PORT_NUM = 0; 
int RecordRate = 3000; 
FILE *fp;

typedef struct timeval timeval;
timeval time_;


void error(const char *msg)
{
    perror(msg);
    exit(1);
}

 //NEW STUFF ADDED
 //void sig_handler(int signo)
 //{
 //  if (signo == SIGINT) {
 // printf("received SIGINT\n");
 // exit(0);
 // fflush(fp);
 // }
 //}

 int main(int argc, char *argv[])
 {
     int sockfd, newsockfd, portno;
     socklen_t clilen;
     char buffer[1000000];
     struct sockaddr_in serv_addr, cli_addr;
     int n;



     PORT_NUM = atoi(argv[1]);  
     fp = fopen(argv[2],"w");   

//       NEW STUFF ADDED
//       if (signal(SIGINT, sig_handler) == SIG_ERR)
//       printf("\ncan't catch SIGINT\n");

     sockfd = socket(AF_INET, SOCK_STREAM, 0);
     if (sockfd < 0) 
            error("ERROR opening socket");
     bzero((char *) &serv_addr, sizeof(serv_addr));
     //portno = atoi(argv[1]);
     portno = PORT_NUM;
     serv_addr.sin_family = AF_INET;
     serv_addr.sin_addr.s_addr = INADDR_ANY;
     serv_addr.sin_port = htons(portno);
     if (bind(sockfd, (struct sockaddr *) &serv_addr,
                        sizeof(serv_addr)) < 0) 
                        error("ERROR on binding");
     listen(sockfd,10);
     clilen = sizeof(cli_addr);



     newsockfd = accept(sockfd, 
                             (struct sockaddr *) &cli_addr, 
                             &clilen);
     if (newsockfd < 0) 
                error("ERROR on accept");


    int counter = 0;    
    int total_bytes_sent = 0;

     while(1){  

     bzero(buffer,1000000);
     n = read(newsockfd,buffer,999999);


     if (n < 0) {
     error("ERROR reading from socket");
     }
     else if (n != 0) {





             total_bytes_sent += n;
             gettimeofday(&time_, NULL);

             if(counter%RecordRate==0){
             printf("counter  %d \n", counter); 
             printf("Bytes Sent  %d \n", total_bytes_sent);
             fprintf(fp,"\"%d\",\"%ld\",\"%d\",\"%d\",\"%d\"\n", counter, time_.tv_sec, time_.tv_usec, n,total_bytes_sent);
             }




             counter++; 



     }

     }
     fclose(fp);
     close(newsockfd);
     close(sockfd);
     return 0; 
 }

我发誓我不是在拖钓。我担心这是我添加的内容,但是一旦我将其注释掉,我就会遇到同样的错误。问题是我添加代码后才出现错误。那么因果关系,相关性,没有联系?

怎么会这样?为什么总是在 2100000000 字节左右。

这不是世界末日。我的意思是我可以硬编码一些东西来确保价值总是积极的,但我很好奇这是怎么发生的。谢谢。

【问题讨论】:

  • 2100000000 周围是 2147483647,这是最大 32 位 int 数字。你从这里拿走。
  • 也许您需要将 int 更改为 unsigned。假设int 是四个字节。 2100000000 接近于 0x80000000,这将被视为负数。
  • Unigend 只会将他的问题从发生在 2 位 GB 转移到 4 位 GB。对于这个用例,32bit 根本不够用,他应该使用 64bit 数据类型。
  • 显然应该添加一个检查以避免像 Y2K 错误这样的东西..
  • 请注意,您所描述的行为不是随机的(如标题所示);它很容易重现,而且变化是系统的。

标签: c server flush integer-overflow


【解决方案1】:

只是因为普通有符号int 变量在 231-1 (2147483647) 处溢出并变为负数。

由于这个数量级不足以跟踪您需要的值,因此您应该使用 64 位变量 - 将您的变量声明为 long long - 并在您所在的位置妥善处理此更改将此值输出到文本流,你应该很好。

【讨论】:

  • 天哪。哈哈。谢谢
  • 从技术上讲,当有符号整数溢出时,您会产生未定义的行为。然而,未定义行为的最常见表现确实是对最负数 (-2147483648) 的环绕,然后从那里开始。不过,假设会发生这种情况并不安全。
  • @Jonathan:但我认为,假设这里正在发生这种情况是(相当)安全的。
  • @RudyVelthuis:这就是 OPs 当前系统上的当前编译器似乎正在发生的事情。但是不要忘记,编译器编写者一直在寻找(让程序员的生活变得困难)优化代码的方法,他们的优化可以假设undefined behaviour is not invoked,事情可以在下一次编译器升级后或当你切换平台等时出现问题。对调用未定义的行为要非常非常谨慎。 (不:我对此不满意。)
  • @我的意思只是这似乎发生在这里。我并不是说应该调用未定义的行为,尽管我敢打赌,在大多数 32 位系统上,同样会发生。请注意,有足够的代码依赖于这种或类似的行为,例如校验码等
猜你喜欢
  • 2017-10-19
  • 2021-12-25
  • 1970-01-01
  • 2020-06-07
  • 1970-01-01
  • 1970-01-01
  • 2016-10-07
  • 2012-02-12
  • 1970-01-01
相关资源
最近更新 更多