具有Dirent结构的分段错误

时间:2018-12-13 17:57:22

标签: c pointers segmentation-fault dirent.h

我正在编写一个小的客户端/服务器C程序。客户端中的一个函数将用于询问服务器目录中所有常规文件的名称。服务器将通过TCP以char数组的形式返回文件名。我的程序有很多选择,可以单独运行任何次数,并且可以轻松切换。当我尝试运行该函数以获取文件名时,出现段错误,并且不知道为什么。我已经在下面粘贴了客户端和服务器代码。

服务器:

void dir_details(int socket) {
    //Set up appropriate variables
    char StringArray[1024];
    struct dirent *de;
    struct stat st = {0};

    //If the upload directory doesn't exist, create it
    if (stat("upload", &st) == -1) {
        mkdir("upload", 0777);
    }

    //Opening the upload directory to be read
    DIR *dr = opendir("upload");

    if (dr == NULL) {
        printf("Could not open directory.");
    }

    //Add each file name to a char array
    while ((de = readdir(dr)) != NULL) {
        strcat(StringArray, de->d_name);
        strcat(StringArray, "\n");
    }

    closedir(dr);
    size_t n = sizeof(StringArray);
    //Send the char array back to the client
    writen(socket, (unsigned char *) &n, sizeof(size_t));   
    writen(socket, (unsigned char *) StringArray, n);   
    strcpy(StringArray, "");
    free(de);
}

客户:

void dir_details(int socket) {
    //Set up char array to be received form the server
    char dirdetails[5000];
    size_t k;

    //Receive char array from the server
    readn(socket, (unsigned char *) &k, sizeof(size_t));    
    readn(socket, (unsigned char *) &dirdetails, k);

    //Print the array to the client
    printf("%s\n", dirdetails);
}

1 个答案:

答案 0 :(得分:2)

仔细阅读 readdir(3)。实际上,struct dirent的最后一个成员d_name可能会像flexible array member那样运行,即使它可能没有完全记录下来。

您的StringArray可能有一个buffer overflow(并且您检查得不够仔细)。您忘记将其归零(至少使用memset(StringArray, 0, sizeof (StringArray)); ...)

当然,您误解了malloc。它可能会失败,并且您始终需要使用它的结果。进一步了解C dynamic memory allocation

阅读How to debug small programs。编译所有警告和调试信息,如果使用GCC,则使用gcc -Wall -Wextra -g

花几天时间阅读有关基本C编程的更多信息。阅读一些C tutorial。查看一些C reference网站。如有疑问,请阅读有关C编程的好教程后,再检查C11标准n1570。研究小型free software程序的源代码以获取灵感。

提高了基本的C编程技能后,请阅读有关Linux编程的知识,例如ALP

销毁您的废话程序(它有很多错误,因此不值得改进或尝试挽救)。 一旦您提高了C编程水平,就可以从头开始重新编写程序。使用一个好的版本控制系统(我建议使用git),并做一些非常iterative and incremental development的操作(写一两行,将它们与所有警告一​​起编译,将其改进为没有警告,使用GDB debugger对其进行测试,然后将其提交给您的版本控制,然后重复所有操作)。仔细阅读正在使用的每个函数的文档(例如{man页,例如read(2)syscalls(2)errno(3)printf(3),等等...)

NB。在触摸键盘之前,您可能应该花至少一个星期的时间阅读。我实际上建议阅读SICP(这是一本很好的编程入门,它不使用C,但是却讲授了非常重要和相关的概念)