我正在尝试创建基于C的HTML客户端。我对C内存泄漏调试很陌生,所以请参阅HTML响应解析器的(简化)代码:
//=============
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int str_index_of(const char *a, char *b) {
char *offset = (char *) strstr(a, b);
return offset - a;
}
char *get_until(char *haystack, char *until) {
int offset = str_index_of(haystack, until);
return strndup(haystack, offset);
}
char *str_replace(const char *search, const char *replace, const char *subject) {
size_t search_size = strlen(search);
size_t replace_size = strlen(replace);
size_t subject_size = strlen(subject);
// Count the number of occurrences of search in subject
size_t count = 0;
const char *p = subject;
while ((p = strstr(p, search)) != NULL) {
count++;
p += search_size;
}
// Allocate memory for the new string
size_t new_size = subject_size + count * (replace_size - search_size);
char *new_subject = (char *) calloc(new_size + 1, sizeof(char));
// Replace search with replace in subject
const char *old = subject;
char *new_p = new_subject;
while ((p = strstr(old, search)) != NULL) {
size_t old_size = p - old;
memcpy(new_p, old, old_size);
new_p += old_size;
memcpy(new_p, replace, replace_size);
new_p += replace_size;
old = p + search_size;
}
strcpy(new_p, old);
return new_subject;
}
void getStatusCode(char *response, char *status_code) {
char *status_line = get_until(response, "\r\n");
status_line = str_replace("HTTP/1.1 ", "", status_line);
char *code = strndup(status_line, 4);
code = str_replace(" ", "", code);
status_code = strcpy(status_code, code);
free(code);
free(status_line);
}
void mockRequest(char *status_code) {
char *res = "HTTP/1.1 200 OK\n"
"Server: nginx\n"
"Date: Fri, 07 Apr 2023 18:44:22 GMT\n"
"Content-Type: application/json; charset=utf-8\n"
"Connection: close\n"
"Access-Control-Allow-Origin: *\n"
"\n"
"73\n"
"some-body-content-here\n"
"0";
char *status_line = NULL;
getStatusCode(res, status_code);
free(status_line);
}
int main() {
char status_code[4];
mockRequest(status_code);
printf("STATUS: %s", status_code);
return 0;
}
//=============
我用地址消毒器。消毒器报告:
==8055==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 190 byte(s) in 1 object(s) allocated from:
#0 0x7f31ccabc808 in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cc:144
#1 0x7f31cca25243 in __interceptor_strndup ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:379
#2 0x55d0abad935c in get_until /home/user/CLionProjects/untitled/main.c:12
#3 0x55d0abad94e0 in getStatusCode /home/user/CLionProjects/untitled/main.c:48
#4 0x55d0abad959d in mockRequest /home/user/CLionProjects/untitled/main.c:70
#5 0x55d0abad963f in main /home/user/CLionProjects/untitled/main.c:78
#6 0x7f31cc7e1082 in __libc_start_main ../csu/libc-start.c:308
Direct leak of 5 byte(s) in 1 object(s) allocated from:
#0 0x7f31ccabc808 in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cc:144
#1 0x7f31cca25243 in __interceptor_strndup ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:379
#2 0x55d0abad9513 in getStatusCode /home/user/CLionProjects/untitled/main.c:50
#3 0x55d0abad959d in mockRequest /home/user/CLionProjects/untitled/main.c:70
#4 0x55d0abad963f in main /home/user/CLionProjects/untitled/main.c:78
#5 0x7f31cc7e1082 in __libc_start_main ../csu/libc-start.c:308
SUMMARY: AddressSanitizer: 195 byte(s) leaked in 2 allocation(s).
泄漏是在调用strndup时,如果我理解得很好。我完全不知道泄漏可能位于何处。您的建议?
2条答案
按热度按时间ni65a41a1#
注意,变量
code
存储strndup
的结果,但在下一行code
被重新分配给str_replace
的结果。strndup
分配的内存永远不会释放,也不能释放,因为不再有指向它的指针。status_line
也存在同样的问题。为了避免将来发生这种情况,请确保每个内存分配都维护一个指向它的指针,该指针可以被释放。
ny6fqffe2#
泄漏原始
status_line
,因为str_replace()
为替换的副本分配了新的内存。您需要将结果分配给一个新变量,以便释放原始变量。