从 std::string 转换为 const char* 导致 valgrind 出现 'Syscall param socketcall.sendto(msg) points to unaddressable byte(s)' 错误
converting from std::string to const char* causes 'Syscall param socketcall.sendto(msg) points to unaddressable byte(s)' error in valgrind
在使用 libmicrohttpd 库时,我在将 string
转换为 const char *
并用它调用 MHD_create_response_from_buffer
时遇到了一个奇怪的错误.
这会导致网页响应返回时格式严重错误,偶尔会显示二进制数据,并且在极少数情况下会导致浏览器认为它是一个文件并进行下载。
真正奇怪的是,如果我发送常规的 const char,则不会显示错误,例如
const char *cstring = "this is a page";
仅当我从 string
转换为 const char *
时
const char *cstring = page.c_str();
Valgrind 输出:
==11105== Thread 2:
==11105== Syscall param socketcall.sendto(msg) points to unaddressable byte(s)
==11105== at 0x617464B: send (send.c:31)
==11105== by 0x565986F: ??? (in /usr/lib/x86_64-linux-gnu/libmicrohttpd.so.10.27.0)
==11105== by 0x565737D: ??? (in /usr/lib/x86_64-linux-gnu/libmicrohttpd.so.10.27.0)
==11105== by 0x565DA3C: MHD_run_from_select (in /usr/lib/x86_64-linux-gnu/libmicrohttpd.so.10.27.0)
==11105== by 0x565DC8A: ??? (in /usr/lib/x86_64-linux-gnu/libmicrohttpd.so.10.27.0)
==11105== by 0x565DDA1: ??? (in /usr/lib/x86_64-linux-gnu/libmicrohttpd.so.10.27.0)
==11105== by 0x876B0A3: start_thread (pthread_create.c:309)
==11105== by 0x617362C: clone (clone.S:111)
==11105== Address 0xe499448 is 24 bytes inside a block of size 56 free'd
==11105== at 0x4C2A360: operator delete(void*) (vg_replace_malloc.c:507)
==11105== by 0x401CA5: http_connect(void*, MHD_Connection*, char const*, char const*, char const*, char const*, unsigned long*, void**) (in /home/shpoople/projects/http/main)
==11105== by 0x5656F70: ??? (in /usr/lib/x86_64-linux-gnu/libmicrohttpd.so.10.27.0)
==11105== by 0x5658427: ??? (in /usr/lib/x86_64-linux-gnu/libmicrohttpd.so.10.27.0)
==11105== by 0x565D988: MHD_run_from_select (in /usr/lib/x86_64-linux-gnu/libmicrohttpd.so.10.27.0)
==11105== by 0x565DC8A: ??? (in /usr/lib/x86_64-linux-gnu/libmicrohttpd.so.10.27.0)
==11105== by 0x565DDA1: ??? (in /usr/lib/x86_64-linux-gnu/libmicrohttpd.so.10.27.0)
==11105== by 0x876B0A3: start_thread (pthread_create.c:309)
==11105== by 0x617362C: clone (clone.S:111)
==11105==
以及发送数据的函数(在 this page 找到,仅修改为使用 std::string
):
static int send_page (struct MHD_Connection *connection, std::string page) {
int ret;
struct MHD_Response *response;
const char* cstring = page.c_str();
response = MHD_create_response_from_buffer (strlen (cstring), (void *) cstring, MHD_RESPMEM_PERSISTENT);
if (!response) {
return MHD_NO;
}
ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
MHD_destroy_response (response);
return ret;
}
我好像自己解决了。抱歉问了一个不必要的问题。
问题已通过将 MHD_create_response_from_buffer
上的第三个参数从 MHD_RESPMEM_PERSISTENT
更改为 MHD_RESPMEM_MUST_COPY
解决
再次抱歉。
您的参数std::string page
是局部变量。当这个函数完成时,它的内存被释放。
另一方面,函数 MHD_run_from_select
和相关的 运行 显然位于单独的线程中。当该线程尝试访问缓冲区时,std::string page
的内存已被释放。
您应该通过以不同方式分配缓冲区或阻塞主线程直到获得响应来确保缓冲区保持活动状态。
在使用 libmicrohttpd 库时,我在将 string
转换为 const char *
并用它调用 MHD_create_response_from_buffer
时遇到了一个奇怪的错误.
这会导致网页响应返回时格式严重错误,偶尔会显示二进制数据,并且在极少数情况下会导致浏览器认为它是一个文件并进行下载。
真正奇怪的是,如果我发送常规的 const char,则不会显示错误,例如
const char *cstring = "this is a page";
仅当我从 string
转换为 const char *
时
const char *cstring = page.c_str();
Valgrind 输出:
==11105== Thread 2:
==11105== Syscall param socketcall.sendto(msg) points to unaddressable byte(s)
==11105== at 0x617464B: send (send.c:31)
==11105== by 0x565986F: ??? (in /usr/lib/x86_64-linux-gnu/libmicrohttpd.so.10.27.0)
==11105== by 0x565737D: ??? (in /usr/lib/x86_64-linux-gnu/libmicrohttpd.so.10.27.0)
==11105== by 0x565DA3C: MHD_run_from_select (in /usr/lib/x86_64-linux-gnu/libmicrohttpd.so.10.27.0)
==11105== by 0x565DC8A: ??? (in /usr/lib/x86_64-linux-gnu/libmicrohttpd.so.10.27.0)
==11105== by 0x565DDA1: ??? (in /usr/lib/x86_64-linux-gnu/libmicrohttpd.so.10.27.0)
==11105== by 0x876B0A3: start_thread (pthread_create.c:309)
==11105== by 0x617362C: clone (clone.S:111)
==11105== Address 0xe499448 is 24 bytes inside a block of size 56 free'd
==11105== at 0x4C2A360: operator delete(void*) (vg_replace_malloc.c:507)
==11105== by 0x401CA5: http_connect(void*, MHD_Connection*, char const*, char const*, char const*, char const*, unsigned long*, void**) (in /home/shpoople/projects/http/main)
==11105== by 0x5656F70: ??? (in /usr/lib/x86_64-linux-gnu/libmicrohttpd.so.10.27.0)
==11105== by 0x5658427: ??? (in /usr/lib/x86_64-linux-gnu/libmicrohttpd.so.10.27.0)
==11105== by 0x565D988: MHD_run_from_select (in /usr/lib/x86_64-linux-gnu/libmicrohttpd.so.10.27.0)
==11105== by 0x565DC8A: ??? (in /usr/lib/x86_64-linux-gnu/libmicrohttpd.so.10.27.0)
==11105== by 0x565DDA1: ??? (in /usr/lib/x86_64-linux-gnu/libmicrohttpd.so.10.27.0)
==11105== by 0x876B0A3: start_thread (pthread_create.c:309)
==11105== by 0x617362C: clone (clone.S:111)
==11105==
以及发送数据的函数(在 this page 找到,仅修改为使用 std::string
):
static int send_page (struct MHD_Connection *connection, std::string page) {
int ret;
struct MHD_Response *response;
const char* cstring = page.c_str();
response = MHD_create_response_from_buffer (strlen (cstring), (void *) cstring, MHD_RESPMEM_PERSISTENT);
if (!response) {
return MHD_NO;
}
ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
MHD_destroy_response (response);
return ret;
}
我好像自己解决了。抱歉问了一个不必要的问题。
问题已通过将 MHD_create_response_from_buffer
上的第三个参数从 MHD_RESPMEM_PERSISTENT
更改为 MHD_RESPMEM_MUST_COPY
再次抱歉。
您的参数std::string page
是局部变量。当这个函数完成时,它的内存被释放。
另一方面,函数 MHD_run_from_select
和相关的 运行 显然位于单独的线程中。当该线程尝试访问缓冲区时,std::string page
的内存已被释放。
您应该通过以不同方式分配缓冲区或阻塞主线程直到获得响应来确保缓冲区保持活动状态。