0

所以我搜索并查看了所有的 snprintf()、sprintf() 和分段错误线程,但仍然无处...

基本上,似乎仅仅存在 snprintf() 语句就导致我的代码出现分段错误。长话短说,是的,这是做作业的……基本上,我必须填写缺失的代码,并且严格遵守命令,不要触碰已经存在的代码。这是我的代码的样子:

        struct dirent* dirEntryPtr;
        struct stat statBuffer;
        char *yourFileName;
        while((dirEntryPtr=readdir(dirPtr))!=NULL)
        {
            int yourFileSize;
            memset(buffer,'\0',sizeof(buffer));
            yourFileName=dirEntryPtr->d_name;
            printf("Directory entry read...%s\n",yourFileName);
            snprintf(buffer,MAX_LINE,"%s/%s",DIR_NAME,yourFileName);
            printf("Printed directory entry to buffer...\n");
            stat(buffer,&statBuffer);
            yourFileSize=statBuffer.st_size;
            printf("File size: %d\n",yourFileSize);
            if(S_ISREG(statBuffer.st_mode))
                {   
                printf("REGULAR!\n");
                snprintf(buffer,MAX_LINE,"%30s (%5d)\n",yourFileName,yourFileSize);
                printf("[%s] %30s (%5d)\n",(char *)statBuffer.st_mode,yourFileName,yourFileSize);
                }
            else
            if(S_ISDIR(statBuffer.st_mode)){
                printf("DIRECTORY!\n");
                snprintf(buffer,MAX_LINE,"%30s (dir)\n",yourFileName);
                printf("[%s] %30s (dir)\n",(char *)statBuffer.st_mode,yourFileName);}
            else
                {
                printf("OTHER!!\n");
                snprintf(buffer,MAX_LINE,"%30s (other)\n",yourFileName);
                printf("[%s] [%s] %30s (other)\n",(char*) S_ISREG(statBuffer.st_mode),(char *)statBuffer.st_mode,yourFileName);
                }                   
            printf("Writing buffer \"%s\" to client...\n",buffer);
            write(clientDescriptor,buffer,MAX_LINE);
            free(buffer);
        }
        close(clientDescriptor);
        exit(EXIT_SUCCESS);

所有的 printf() 基本上都用于调试。(是的,我知道,使用 GDB,但尽管经过多年的指导,我还是无法弄清楚它是如何工作的!)

长话短说,当前目录中的文件被读取,一次一个。第一个文件通常是名为 server.c 的文件,它始终被正确识别为“常规”文件。然而,当 snprintf() 行进入时,就是分段错误发挥作用的地方。缓冲区是一个声明的字符串(我不允许触摸的部分代码,但说明是专门使用 snprintf() 将条目写入“缓冲​​区” - 事实上,我正在使用 EXACT snprintf() 命令是说明中给出的内容!)并设置为 MAX_LINE 字节(80),这是在包含的外部头文件中#defined。我之前在那里有一个 strnlen 用于调试目的,以确认 DIR_NAME 是一个字符,而 yourFileName 至少在 server.c 的情况下是 9 - 远不及 80!

我什至尝试声明一个新变量并通过 snprintf() 向它写入一个字节,但仍然出现分段错误!我已经尝试过使用和不使用 malloc() 命令。

我还应该寻找什么???我确实给我的教授发了电子邮件,但说实话,我必须提交这个,比如今天(几天后才到期,但我要出城了),只需要尽快指点......但根据我对C的理解,这应该可行。事实上,它实际上在昨天下午工作,但突然间它在昨晚深夜开始对我造成分段错误。:(

4

2 回答 2

2

这是一个可能的原因:

printf("[%s] [%s] %30s (other)\n",
       (char*) S_ISREG(statBuffer.st_mode),
       (char *)statBuffer.st_mode,
       yourFileName);

这指示printf()

  • 将 的返回值S_ISREG()视为指向空终止字符串的指针,它不是并且将是01(基于以下从 中提取的内容sys/stat.h):

    #define __S_ISTYPE(mode, mask)  (((mode) & __S_IFMT) == (mask))
    
    #define S_ISREG(mode)    __S_ISTYPE((mode), __S_IFREG)
    
  • st_mode其视为指向非空终止字符串的指针(AFAIK 的类型st_modeint

要修复用作%d格式说明符而不是%sOR,S_ISREG()您可以使用三元运算符并返回字符串文字:

printf("[%s] [%d] %30s (other)\n",
       S_ISREG(statBuffer.st_mode) ? "regular file" : "not regular file",
       statBuffer.st_mode,
       yourFileName);

这是一个错误,几乎可以肯定是原因:

char buffer[MAX_LINE];

free(buffer);

只传递给free()动态分配的内容

free 函数会导致 ptr 指向的空间被释放,也就是说,可用于进一步分配。如果 ptr 是空指针,则不会发生任何操作。否则,如果参数与 calloc、malloc 或 realloc 函数先前返回的指针不匹配,或者如果空间已通过调用 free 或 realloc 被释放,则行为未定义。

于 2012-08-15T14:56:58.163 回答
1

另一个错误:

write(clientDescriptor,buffer,MAX_LINE);

buffer如果指向 NUL 终止的字符串,几乎肯定不是您想要的。这总是写入MAX_LINE字符并且不会在 NUL 处停止。我建议fprintf和朋友 ( puts, fputs) 输出字符串。

于 2012-08-15T15:49:21.187 回答