簡體   English   中英

Valgrind:大小為1的讀/寫無效

[英]Valgrind: Invalid read / write of size 1

我正在嘗試使用C構建一個非常基本的Web服務器。 我已經解決了valgrind報告的valgrind問題,除了這個問題。 這是導致它的相關代碼段。 我已將valgrind x>>添加到valgrind建議的行中:

/* Set the response header. */
char *response_header = "HTTP/1.1 404 Not Found\r\n"
        "Content-Type: text/html\r\n"
        "Connection: close\r\n"
        "\r\n";

/* Try to load the 404 message. Return 0 if failed. */
int response_body_size = 0;
char *response_body = read_file(FILE_404, &response_body_size);
if (response_body == NULL) {
    return 0;
}
terminate_string(response_body, response_body_size);

/* Allocate space to merge the header and body and merge them. Return 0 if failed. */
1>> char *response = (char *) malloc(sizeof(char) * (strlen(response_header) + strlen(response_body)));
if (response == NULL) {
    return 0;
}
strcpy(response, response_header);
2,3>> strcat(response, response_body);

/* Return the response. */
4>> write(connection_fd, response, strlen(response));

terminate_string():

/* Adds the terminating character to the specified string. */
void terminate_string(char *str, int length) {
5>> str[length] = '\0';
}

read_file():

/* Reads the specified file and returns its contents. Will return NULL if could not read. */
/* Assumes the filename starts with a / character! */
void* read_file(char *filename, int *file_size) {
    /* Open the file in binary read mode. Return NULL if failed. */
    FILE *file = fopen(filename + 1, "rb");
    if (file == NULL) {
        return NULL;
    }

    /* Get the size of the file. Return NULL if failed.*/
    struct stat fs;
    if (fstat(fileno(file), &fs) == -1) {
        return NULL;
    }

    *file_size = fs.st_size;

    /* Read the contents to a string. */
    void* result = NULL;
6>> result = (void *) malloc (fs.st_size);
    /* Return NULL if malloc failed. */
    if (result == NULL) {
        return NULL;
    }
    fread(result, 1, *file_size, file);

    /* Close the file. */
    fclose(file);

    return result;
}

Valgrind報告:

1: Invalid read of size 1 [PID: 3896]
2: Invalid read of size 1 [PID:3896]
3: Invalid write of size 1 [PID:3896]
4: Invalid read of size 1 [PID:3896]
5: Invalid write of size 1 [PID:3896]
6: Address 0x541bbb4 is 0 bytes after a block of size 4 alloc'd [PID: 3896]

由於某種原因, read_file()函數返回2個額外的字符。 這似乎是通過terminate_string()解決的,但顯然valgrind知道我不知道的事情。 我一直在看這個代碼過去3個小時,同時閱讀我在網上發現的每一個可能的解決方案,我沒有設法解決它。 我對C中的動態內存分配很新,所以對於有經驗的人來說這可能是非常明顯的。

這里有什么問題,我該如何解決?

另外, 為什么read_file()返回的文件比文件包含的多2個字節?

首先,使用valgrind做得很好。

在第6點,你做:

result = (void *) malloc (fs.st_size);

我建議你這樣做:

size_t sz = fs.st_size;
result = malloc (sz+1); /* no need to cast return of malloc() */
((char *)result)[sz] = 0; /* zero terminate it */

當你有問題,你有malloc “D 恰好足夠的空間用於文件和身體,但不包括終止NUL

你的terminate_string想法被破壞了,因為它超出了response_body的末尾。 如果響應主體為零終止,則不需要它,因此可以刪除它。

出於類似的原因,您需要:

char *response = malloc(sizeof(char) *
                 (strlen(response_header) + strlen(response_body) + 1));

+1代表NUL

但是,有一個更大的問題:HTTP文檔本身可以包含\\0 ,即零字節,在這種情況下你不能strlen()它們。 因此,更好的解決方法是write響應頭,然后write響應體,並簡單地將體的大小保持為整數。 我已經解釋了上面的問題,因為重要的是你知道。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM