【问题标题】:Segmentation Fault, debugging分段故障,调试
【发布时间】:2014-04-09 16:08:36
【问题描述】:

我的程序代码在几个小时前还在工作,我似乎在想是什么我改变了它给它一个分段错误。我很难找到这个讨厌的小错误,如果有人能告诉我调试这样的东西的最佳方法,那就太棒了。

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


/*  VSIE client program uses TCP protocol to connect to the remote http server.
    The program will take 2 input arguments:
        1) command option, get (receive) or head (send)
        2) http URL address 
*/

#define MAX 80
#define MAX2 1024
#define http "HTTP/1.1"
#define TRUE   1
#define FALSE  0
#define HEADERSTOP "\n\n"
main(int argc, char *argv[])
{   
    char *temp;
    unsigned char *e;
    char *line;
    char command[MAX];
    char server[MAX];
    char path[MAX];
    char filename[MAX]= "";
    char httpString[MAX];
    int i, x, f, n, length = 0;
    int numBytes = 0;
    int getData = TRUE;
    int getFlag = FALSE;
    int flag = FALSE;
    int headFlag = FALSE;
    FILE *in;

    int sk;
    unsigned char buf[MAX2];
    struct sockaddr_in remote;
    struct hostent *hp;
    struct servent *sp;
    short port = 0;


    // parse input arguments
    sscanf(argv[2],"%[^'/']%s",server,path);

    if (strcmp(argv[1],"-get") == 0)
    {
        sprintf(command, "GET");
        getFlag = TRUE;
    }
    else if (strcmp(argv[1],"-head") == 0)
    {
        sprintf(command, "HEAD");
    }

    //build http 1.1 GET or HEAD message
    sprintf(httpString,"%s %s %s\nHost: %s\n\n", command, path,http,server);

    printf("command = %s, server = %s, path = %s\n", command, server, path);
    printf("httpString = %s\n",httpString);

    //parse filename from path
    length = strlen(path);
    x=0;
    f=0;

    for(i = 0; i < length; i++)
    {
        //printf("path[%d] = %c \n",i,path[i]);
        if ((flag == TRUE) & (f == 2))
        {
            filename[x] = path[i];
            x++;
        }

        if (path[i] == '/')
        {
            flag = TRUE;
            f++;
        }

    }

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

    //if command = get, open filename   
    //if(command == "-get") 
    if (getFlag == TRUE)
    {
        if((in = fopen (filename,"w")) == NULL)
        {
            //printf("FAILURE: opening input file %s\n",filename);
            perror("FAILURE: opening input file");
            exit(1);
        }
        printf("file opened successfully\n");
    }

    //get internet address of host & port number of http service
    hp = gethostbyname(server);
    if (hp == NULL) 
    {
        printf("Can't find host name. %s\n", server);
        exit (1);
    }

    //copy the h_addr (source) to s_add (destination) for n bytes specified by length
    bcopy(hp->h_addr,&remote.sin_addr.s_addr,hp->h_length);

    /* get the port     number */
    sp = getservbyname("http", "tcp");
    if (sp == NULL)
    {
        printf("can't find port # %d\n",sp->s_port);
        exit (1);
    }
    port = sp->s_port;
    remote.sin_port = sp->s_port;
    printf("port = %d, port = %d \n", port, remote.sin_port);

    //create socket for http server - socket type: Sock_Stream, protocol: TCP
    sk = socket(AF_INET,SOCK_STREAM,0);
    if (sk < 0)
    {
        perror("error opening socket");
        exit(1);
    }
    remote.sin_family = AF_INET;    

    //initiate connection to the server address w/ TCP socket
    if (connect(sk, (struct sockaddr *) &remote, sizeof(remote)) < 0) 
    {
        printf("connect fails!\n");
        exit(1);
    }
    printf("connection successful\n");

    //send http message
    printf("send message:%s\n", httpString);
    //send(sk,httpString,strlen(httpString)+1,0);
    if(send(sk,httpString,sizeof(httpString),0) < 0)
    {
        printf("send() failed");
        //exit(1);
    }

    n = 1;
    //Loop until all data received
    while(getData == TRUE)
    {   
        //wait for and print the return message
        numBytes = recv(sk,buf,sizeof(buf),0);
        if (numBytes < 0)
        {
            perror("error reading from socket");
            break;
        }
        else if (numBytes < MAX2)
        {
            getData = FALSE;
            printf("***end while loop****\n");
        }
        if (headFlag == FALSE){

            e = memchr(buf, '\n', sizeof(buf)); 

            while (*(e+1) != '\r'){
                e = memchr(e+1, '\n', sizeof(buf));
            }       
            sprintf(temp, "%s", e);
            headFlag = TRUE;
        }



        printf("\n****number of bytes received %d****\n",numBytes); 
        line = strtok(buf, "\n");
        while(line != NULL) {
            if (strstr(line, "Content-Length:")!= NULL){
                int dataSize;
                sscanf(line, "Content-Length: %d", &dataSize);
                printf("The Data Size: %d\n", dataSize);
            }
            line = strtok(NULL, "\n");


        //saved the retrieved content into the file (input argument)

        if (getFlag == TRUE)
        {
            //printf("write output\n");

            if(e != NULL){
                printf("%.*s\n", (int)(numBytes-sizeof(temp)), buf);
                fwrite(temp, sizeof(temp), 1, in);
                e = NULL;
            }else{
                fwrite(buf, numBytes, 1, in);
            }

        }
        n++;
    } // end while()

    //close socket & file
    close(sk);

    if(fclose(in) !=0)
    {
        perror("FAILURE: Closing input file");
        exit(1);
    }

    return 0;
} //end main()

【问题讨论】:

  • 最好的调试方式是使用调试器
  • 我从未真正使用过 gdb,所以我不太确定我在用它做什么。
  • 编写一个没有调试器的 hello world 程序就可以了。没有这个程序。如果你想在让代码工作方面取得更快的进展,我会投资阅读和学习如何使用调试器。这也将帮助您缩小需要发布的任何问题的范围。
  • 您声明了许多大小为MAX 的缓冲区,您已将其定义为80。然后,您将这些缓冲区用于可能超过 80 个字符的各种事情,尤其是httpString。尝试将MAX 增加到您可以合理确定不会溢出的值,例如 4096。然后,如果它修复了您的段错误,您将更好地了解在哪里寻找导致它的原因。如果它不能解决您的段错误,那么至少您已经消除了一个非常常见的段错误原因。
  • 另外,学习使用gdb 一点也不难。不要回避它,因为你认为它会有一些陡峭的学习曲线。如果您不想从命令行调试,还有很多 GUI frontends 用于 gdb

标签: c linux segmentation-fault


【解决方案1】:

问题在

    sprintf(temp, "%s", e);

 if(fclose(in) !=0)

验证这两个地方的代码。

将这两部分注释掉后,没有分段错误。

【讨论】:

    【解决方案2】:

    使用 -g 选项编译您的代码。

    运行 gdb 为 - gdb /你的可执行文件/

    从 gdb 内部执行 - 运行 /input arguments/

    它应该停在导致分段错误的地方。您应该可以通过 -where

    进行堆栈跟踪

    请参考- http://www.delorie.com/gnu/docs/gdb/gdb_284.html

    【讨论】:

      猜你喜欢
      • 2018-12-21
      • 1970-01-01
      • 2018-01-19
      • 1970-01-01
      相关资源
      最近更新 更多