加载或索引函数中的cs50 pset6错误

时间:2016-08-18 17:47:32

标签: c indexing load cs50

我完成了所有功能的实现,但是我的代码未通过第二次检查。我不确定问题的确切位置,但它可能在我的加载或索引函数中,因为我的代码成功完成了第一次检查。有人可以帮我搞清楚吗?哦,由于某种原因,我的GDB无法正常工作。提前致谢!

这是我的代码:

char *indexes(const char *path) {
    char *copy = malloc(strlen(path)); 
    strcpy(copy, path); 

    char *php = "/index.php\0";
    char *html = "/index.html\0"; 

    char *check_php = malloc(strlen(copy) + strlen(php));
    char *check_html = malloc(strlen(copy) + strlen(html)); 

    check_php = strcat(copy, php); 
    check_html = strcat(copy, html); 

    if (access(check_php, F_OK) == 0)
        return check_php;
    else
    if (access(check_html, F_OK) == 0)
        return check_html; 

    return NULL;
}

bool load(FILE *file, BYTE **content, size_t *length) {
    char *store = malloc(5000); 
    int count = 0; 
    char c; 

    do {
        c = fgetc(file);

        if (feof(file))
            break; 
        else
        if (count % 5000 == 0)
            store = realloc(store, count + 5000);

        store[count] = c;
        count++; 
    } while (true); 

    *content = &store[0]; 
    *length = count;

    return true;
}

3 个答案:

答案 0 :(得分:3)

您的代码中存在许多问题:

  • 函数indexes()中存在一个经典错误:

    char *copy = malloc(strlen(path)); 
    strcpy(copy, path); 
    

    您必须为空终止符分配一个字节:

    char *copy = malloc(strlen(path) + 1);
    strcpy(copy, path); 
    

    或者您可以在系统上使用Posix函数strdup()

    char *copy = strdup(path);
    
  • 连接尝试的类似问题:

    char *check_php = malloc(strlen(copy) + strlen(php));
    char *check_html = malloc(strlen(copy) + strlen(html)); 
    
    check_php = strcat(copy, php); 
    check_html = strcat(copy, html); 
    

    您没有分配足够的内存, plus 您没有将字符串复制到已分配的内存中,而是连接到已经填满的copy的末尾。你应该写:

    char *check_php = malloc(strlen(copy) + strlen(php) + 1);
    char *check_html = malloc(strlen(copy) + strlen(html) + 1); 
    
    strcpy(check_php, copy);
    strcpy(check_php, php);
    
    strcpy(check_html, copy);
    strcpy(check_html, html);
    
  • 在离开此功能之前,您没有free不再使用的字符串。这很草率,导致内存泄漏。

功能load()中存在更多不太紧急的问题:

  • fgetc()的返回值应存储在int中。检查文件末尾的方式虽然不是技术上的错误,但是容易出错并且不推荐,你应该写下这个:

    int c = fgetc(fp);
    if (c == EOF)
        break;
    
  • 重新分配方案是多余的:如果count == 0您调用的realloc()与初始malloc()调用的大小相同。您只需将store初始化为NULL,并仅依靠realloc进行分配。如果该文件为空,则*length将设置为0*bytes设置为NULL,这应该没问题。

    另一种方法是在将指针存储到store之前将*bytes重新分配给读取的实际大小。

  • do { ... } while (true);不是读者友好的:使用for (;;) { ... }立即告诉读者这个无限循环的性质会好得多。

答案 1 :(得分:2)

代码中有很多错误。我创建了两个版本。一个带有注释和纠正的错误。另一个清理并简化了。

以下是带#if 0 /*original code*/ #else /*fixed code*/ #endif的注释版本:

char *
indexes(const char *path)
{
    // NOTE/BUG: malloc for string must allow for EOS char
#if 0
    char *copy = malloc(strlen(path));
#else
    char *copy = malloc(strlen(path) + 1);
#endif

    // NOTE/BUG: no need to duplicate path -- it can be used directly
    strcpy(copy, path);

    // NOTE/BUG: the \0 is redundant
#if 0
    char *php = "/index.php\0";
    char *html = "/index.html\0";
#else
    char *php = "/index.php";
    char *html = "/index.html";
#endif

    // NOTE/BUG: malloc for string must allow for EOS char
#if 0
    char *check_php = malloc(strlen(copy) + strlen(php));
    char *check_html = malloc(strlen(copy) + strlen(html));
#else
    char *check_php = malloc(strlen(copy) + strlen(php) + 1);
    char *check_html = malloc(strlen(copy) + strlen(html) + 1);
#endif

    // NOTE/BUG: copy doesn't have enough space to hold the concat and is wrong
    // NOTE/BUG: this is trashing the above values and, thus, leaking memory
#if 0
    check_php = strcat(copy, php);
    check_html = strcat(copy, html);
#else
    strcpy(check_php,copy);
    strcat(check_php,php);
    strcpy(check_html,copy);
    strcat(check_html,html);
#endif

    // NOTE/BUG: this is leaking memory of the unused check_html
#if 0
    if (access(check_php, F_OK) == 0)
        return check_php;
#else
    if (access(check_php, F_OK) == 0) {
        free(check_html);
        return check_php;
    }
#endif

    // NOTE/BUG: this is leaking memory of the unused check_php
#if 0
    if (access(check_html, F_OK) == 0)
        return check_html;
#else
    if (access(check_html, F_OK) == 0) {
        free(check_php);
        return check_html;
    }
#endif

    // NOTE/BUG: this is leaking memory of the unused check_php and check_html
#if 1
    free(check_html);
    free(check_php);
#endif
    return NULL;
}

以下是已清理的版本:

char *
indexes(const char *path)
{
    char *php = "/index.php";
    char *html = "/index.html";
    size_t plen = strlen(path);
    char *file;

    file = malloc(plen + strlen(php) + 1);
    strcpy(file,path);
    strcat(file,php);
    if (access(file, F_OK) == 0)
        return file;
    free(file);

    file = malloc(plen + strlen(html) + 1);
    strcpy(file,path);
    strcat(file,html);
    if (access(file, F_OK) == 0)
        return file;
    free(file);

    return NULL;
}

答案 2 :(得分:1)

如果不是这样,我道歉,但是你不应该为复制分配更多的内存吗?通过定义strcat(char * strcat(char * dest,const char * src)) 参数 dest - 这是指向目标数组的指针,该数组应该包含一个C字符串,而应该足够大以包含连接的结果字符串。但是你只分配复制路径的strlen。