libuv + C++ 段错误
libuv + C++ segfaults
我正在使用 libuv 在 C++ 中为流编写一个包装器,但它会出现段错误,而且我找不到原因。流 class:
class Stream{
public:
Stream(int fd);
void Write(const std::string& data, const std::function<void(void)>& callback);
const static int STDIN = 0;
const static int STDOUT = 1;
private:
static void OnWrite(uv_write_t *req, int status);
uv_pipe_t pipe;
};
以及实施
Stream::Stream(int fd){
uv_pipe_init(uv_default_loop(), &pipe, 0);
uv_pipe_open(&pipe, fd);
}
void Stream::Write(const std::string& data, const std::function<void(void)>& callback){
uv_write_t request;
uv_buf_t buffer = uv_buf_init((char*)malloc(data.length()*sizeof(char)), data.length());
strcpy(buffer.base, data.c_str());
buffer.len = data.length();
uv_write(&request, (uv_stream_t*)&pipe, &buffer, 1, OnWrite);
}
void Stream::OnWrite(uv_write_t *req, int status){
}
我在主文件中这样做:
Stream* out = new Stream(Stream::STDOUT);
out->Write("Hello, World!", []() {
});
uv_run(uv_default_loop(), RUN_DEFAULT);
但是,一旦我 运行 这个,它就会在 uv_run
语句上出现段错误。回溯:
#0 0x00007ffff7bcac94 in uv__write_callbacks (stream=stream@entry=0x603010) at src/unix/stream.c:907
#1 0x00007ffff7bcb0a1 in uv__stream_io (loop=<optimized out>, w=0x603098, events=<optimized out>) at src/unix/stream.c:1243
#2 0x00007ffff7bc31eb in uv__run_pending (loop=0x7ffff7dd98c0 <default_loop_struct>) at src/unix/core.c:710
#3 uv_run (loop=0x7ffff7dd98c0 <default_loop_struct>, mode=UV_RUN_DEFAULT) at src/unix/core.c:316
#4 0x0000000000400fcd in main ()
但是,如果我将 uv_run 放在 Stream::Write
方法中,它就可以正常工作。我该如何解决这个问题?
编辑
我现在在堆上而不是在堆栈上分配管道,但它仍然给我一个段错误。我把header里的uv_pipe_t
改成uv_pipe_t*
,现在实现改成这样:
Stream::Stream(int fd){
pipe = new uv_pipe_t;
uv_pipe_init(uv_default_loop(), pipe, 0);
uv_pipe_open(pipe, fd);
}
void Stream::Write(const std::string& data, const std::function<void(void)>& callback){
uv_write_t request;
uv_buf_t buffer = uv_buf_init((char*)data.c_str(), data.length());
uv_write(&request, (uv_stream_t*)pipe, &buffer, 1, OnWrite);
}
void Stream::OnWrite(uv_write_t *req, int status){
delete req;
}
来自 GDB 的回溯:
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7bcac94 in uv__write_callbacks (stream=stream@entry=0x603030) at src/unix/stream.c:907
907 uv__req_unregister(stream->loop, req);
(gdb) backtrace
#0 0x00007ffff7bcac94 in uv__write_callbacks (stream=stream@entry=0x603030) at src/unix/stream.c:907
#1 0x00007ffff7bcb0a1 in uv__stream_io (loop=<optimized out>, w=0x6030b8, events=<optimized out>) at src/unix/stream.c:1243
#2 0x00007ffff7bc31eb in uv__run_pending (loop=0x7ffff7dd98c0 <default_loop_struct>) at src/unix/core.c:710
#3 uv_run (loop=0x7ffff7dd98c0 <default_loop_struct>, mode=UV_RUN_DEFAULT) at src/unix/core.c:316
#4 0x0000000000400f4d in main ()
你的 "write request" (uv_write_t
) 分配在堆栈上,当 libuv 试图将它的指针传递给写回调函数时(或者,实际上当 libuv 本身试图使用它。)请记住,在 libuv 中一切都是异步的;这可能就是您使用它的原因!
您应该在堆上分配您的 uv_write_t
(或作为 global/class 变量或从池中分配)并记得在写回调中释放它。
您的程序中还有另一个 memory/lifetime 错误,但这不是崩溃错误,而是产生垃圾的错误。您 malloc
放入 uv_buffer_t
的缓冲区不需要,可以在调用后立即释放(这是同步的!)真的,您甚至不需要分配单独的缓冲区;您可以将 data.c_str()
作为第一个参数传递给 uv_buf_init()
.
我正在使用 libuv 在 C++ 中为流编写一个包装器,但它会出现段错误,而且我找不到原因。流 class:
class Stream{
public:
Stream(int fd);
void Write(const std::string& data, const std::function<void(void)>& callback);
const static int STDIN = 0;
const static int STDOUT = 1;
private:
static void OnWrite(uv_write_t *req, int status);
uv_pipe_t pipe;
};
以及实施
Stream::Stream(int fd){
uv_pipe_init(uv_default_loop(), &pipe, 0);
uv_pipe_open(&pipe, fd);
}
void Stream::Write(const std::string& data, const std::function<void(void)>& callback){
uv_write_t request;
uv_buf_t buffer = uv_buf_init((char*)malloc(data.length()*sizeof(char)), data.length());
strcpy(buffer.base, data.c_str());
buffer.len = data.length();
uv_write(&request, (uv_stream_t*)&pipe, &buffer, 1, OnWrite);
}
void Stream::OnWrite(uv_write_t *req, int status){
}
我在主文件中这样做:
Stream* out = new Stream(Stream::STDOUT);
out->Write("Hello, World!", []() {
});
uv_run(uv_default_loop(), RUN_DEFAULT);
但是,一旦我 运行 这个,它就会在 uv_run
语句上出现段错误。回溯:
#0 0x00007ffff7bcac94 in uv__write_callbacks (stream=stream@entry=0x603010) at src/unix/stream.c:907
#1 0x00007ffff7bcb0a1 in uv__stream_io (loop=<optimized out>, w=0x603098, events=<optimized out>) at src/unix/stream.c:1243
#2 0x00007ffff7bc31eb in uv__run_pending (loop=0x7ffff7dd98c0 <default_loop_struct>) at src/unix/core.c:710
#3 uv_run (loop=0x7ffff7dd98c0 <default_loop_struct>, mode=UV_RUN_DEFAULT) at src/unix/core.c:316
#4 0x0000000000400fcd in main ()
但是,如果我将 uv_run 放在 Stream::Write
方法中,它就可以正常工作。我该如何解决这个问题?
编辑
我现在在堆上而不是在堆栈上分配管道,但它仍然给我一个段错误。我把header里的uv_pipe_t
改成uv_pipe_t*
,现在实现改成这样:
Stream::Stream(int fd){
pipe = new uv_pipe_t;
uv_pipe_init(uv_default_loop(), pipe, 0);
uv_pipe_open(pipe, fd);
}
void Stream::Write(const std::string& data, const std::function<void(void)>& callback){
uv_write_t request;
uv_buf_t buffer = uv_buf_init((char*)data.c_str(), data.length());
uv_write(&request, (uv_stream_t*)pipe, &buffer, 1, OnWrite);
}
void Stream::OnWrite(uv_write_t *req, int status){
delete req;
}
来自 GDB 的回溯:
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7bcac94 in uv__write_callbacks (stream=stream@entry=0x603030) at src/unix/stream.c:907
907 uv__req_unregister(stream->loop, req);
(gdb) backtrace
#0 0x00007ffff7bcac94 in uv__write_callbacks (stream=stream@entry=0x603030) at src/unix/stream.c:907
#1 0x00007ffff7bcb0a1 in uv__stream_io (loop=<optimized out>, w=0x6030b8, events=<optimized out>) at src/unix/stream.c:1243
#2 0x00007ffff7bc31eb in uv__run_pending (loop=0x7ffff7dd98c0 <default_loop_struct>) at src/unix/core.c:710
#3 uv_run (loop=0x7ffff7dd98c0 <default_loop_struct>, mode=UV_RUN_DEFAULT) at src/unix/core.c:316
#4 0x0000000000400f4d in main ()
你的 "write request" (uv_write_t
) 分配在堆栈上,当 libuv 试图将它的指针传递给写回调函数时(或者,实际上当 libuv 本身试图使用它。)请记住,在 libuv 中一切都是异步的;这可能就是您使用它的原因!
您应该在堆上分配您的 uv_write_t
(或作为 global/class 变量或从池中分配)并记得在写回调中释放它。
您的程序中还有另一个 memory/lifetime 错误,但这不是崩溃错误,而是产生垃圾的错误。您 malloc
放入 uv_buffer_t
的缓冲区不需要,可以在调用后立即释放(这是同步的!)真的,您甚至不需要分配单独的缓冲区;您可以将 data.c_str()
作为第一个参数传递给 uv_buf_init()
.