了解作用域后堆栈使用错误
Understanding a stack-use-after-scope error
我正在使用 C 和 pthreads 库开发多线程客户端,使用 boss/worker 架构设计,但遇到问题 understanding/debugging 导致我的堆栈使用后范围错误客户端失败。 (我对 C 有点陌生)
我试过很多东西,包括全局定义变量,传递双指针引用等
Boss logic within main:
for (i = 0; i < nrequests; i++)
{
struct Request_work_item *request_ctx = malloc(sizeof(*request_ctx));
request_ctx->server = server;
request_ctx->port = port;
request_ctx->nrequests = nrequests;
req_path = get_path(); //Gets a file path to work on
request_ctx->path = req_path;
steque_item work_item = &request_ctx; // steque_item is a void* so passing it a pointer to the Request_work_item
pthread_mutex_lock(&mutex);
while (steque_isempty(&work_queue) == 0) //Wait for the queue to be empty to add more work
{
pthread_cond_wait(&c_boss, &mutex);
}
steque_enqueue(&work_queue, work_item); //Queue the workItem in a workQueue (type steque_t, can hold any number of steque_items)
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&c_worker);
}
Worker logic inside a defined function:
struct Request_work_item **wi;
while (1)
{
pthread_mutex_lock(&mutex);
while (steque_isempty(&work_queue) == 1) //Wait for work to be added to the queue
{
pthread_cond_wait(&c_worker, &mutex);
}
wi = steque_pop(&work_queue); //Pull the steque_item into a Request_work_item type
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&c_boss);
char *path_to_file = (*wi)->path; //When executing, I get this error in this line: SUMMARY: AddressSanitizer: stack-use-after-scope
...
...
...
continues with additional worker logic
我希望工作人员从队列中拉出 work_item,取消对值的引用,然后执行一些工作。但是,我一直收到 AddressSanitizer: stack-use-after-scope,网上关于这个错误的信息不是很丰富,所以任何指点将不胜感激。
这里的危险信号是&request_ctx
是局部变量的地址。它不是指向用 malloc
分配的存储的指针,而是保存该存储的变量的地址。一旦此范围终止,该变量就会消失,即使 malloc
-ed 块持续存在。
也许修复只是删除此行中的 &
运算符的地址?
steque_item work_item = &request_ctx; // steque_item is a void* so passing
// it a pointer to the Request_work_item
如果我们这样做,那么评论实际上说的是实话。因为否则我们将 work_item
设为 指向 指向 Request_work_item
.
的指针
由于 work_item
的类型为 void
*,不幸的是,它可以通过任何一种方式编译。
如果队列另一端的项目的使用者将其提取为 Request_work_item *
,那么您不仅可以访问超出范围的对象,还可以访问类型不匹配,即使当消费者使用它时该对象恰好仍在生产者的范围内。消费者最终使用生产者堆栈的一部分,就好像它是一个 Request_work_item
结构一样。 编辑: 我看到您在使项目出队并以 (*wi)->path
访问它时使用了指向指针的指针。考虑更改设计以避免这样做。否则,wi
指针也必须动态分配并释放。生产者必须做类似的事情:
struct Request_work_item **p_request_ctx = malloc(sizeof *p_request_ctx);
struct Request_work_item *request_ctx = malloc(sizeof *request_ctx);
if (p_request_ctx && request_ctx) {
*p_request_ctx = request_ctx;
request_ctx->field = init_value;
// ... etc
// then p_request_ctx is enqueued.
消费者然后必须 free
结构,以及 free
指针。那个额外的指针在这里看起来像是纯粹的开销;它不提供任何基本或有用的间接级别。
我正在使用 C 和 pthreads 库开发多线程客户端,使用 boss/worker 架构设计,但遇到问题 understanding/debugging 导致我的堆栈使用后范围错误客户端失败。 (我对 C 有点陌生)
我试过很多东西,包括全局定义变量,传递双指针引用等
Boss logic within main:
for (i = 0; i < nrequests; i++)
{
struct Request_work_item *request_ctx = malloc(sizeof(*request_ctx));
request_ctx->server = server;
request_ctx->port = port;
request_ctx->nrequests = nrequests;
req_path = get_path(); //Gets a file path to work on
request_ctx->path = req_path;
steque_item work_item = &request_ctx; // steque_item is a void* so passing it a pointer to the Request_work_item
pthread_mutex_lock(&mutex);
while (steque_isempty(&work_queue) == 0) //Wait for the queue to be empty to add more work
{
pthread_cond_wait(&c_boss, &mutex);
}
steque_enqueue(&work_queue, work_item); //Queue the workItem in a workQueue (type steque_t, can hold any number of steque_items)
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&c_worker);
}
Worker logic inside a defined function:
struct Request_work_item **wi;
while (1)
{
pthread_mutex_lock(&mutex);
while (steque_isempty(&work_queue) == 1) //Wait for work to be added to the queue
{
pthread_cond_wait(&c_worker, &mutex);
}
wi = steque_pop(&work_queue); //Pull the steque_item into a Request_work_item type
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&c_boss);
char *path_to_file = (*wi)->path; //When executing, I get this error in this line: SUMMARY: AddressSanitizer: stack-use-after-scope
...
...
...
continues with additional worker logic
我希望工作人员从队列中拉出 work_item,取消对值的引用,然后执行一些工作。但是,我一直收到 AddressSanitizer: stack-use-after-scope,网上关于这个错误的信息不是很丰富,所以任何指点将不胜感激。
这里的危险信号是&request_ctx
是局部变量的地址。它不是指向用 malloc
分配的存储的指针,而是保存该存储的变量的地址。一旦此范围终止,该变量就会消失,即使 malloc
-ed 块持续存在。
也许修复只是删除此行中的 &
运算符的地址?
steque_item work_item = &request_ctx; // steque_item is a void* so passing
// it a pointer to the Request_work_item
如果我们这样做,那么评论实际上说的是实话。因为否则我们将 work_item
设为 指向 指向 Request_work_item
.
由于 work_item
的类型为 void
*,不幸的是,它可以通过任何一种方式编译。
如果队列另一端的项目的使用者将其提取为 Request_work_item *
,那么您不仅可以访问超出范围的对象,还可以访问类型不匹配,即使当消费者使用它时该对象恰好仍在生产者的范围内。消费者最终使用生产者堆栈的一部分,就好像它是一个 Request_work_item
结构一样。 编辑: 我看到您在使项目出队并以 (*wi)->path
访问它时使用了指向指针的指针。考虑更改设计以避免这样做。否则,wi
指针也必须动态分配并释放。生产者必须做类似的事情:
struct Request_work_item **p_request_ctx = malloc(sizeof *p_request_ctx);
struct Request_work_item *request_ctx = malloc(sizeof *request_ctx);
if (p_request_ctx && request_ctx) {
*p_request_ctx = request_ctx;
request_ctx->field = init_value;
// ... etc
// then p_request_ctx is enqueued.
消费者然后必须 free
结构,以及 free
指针。那个额外的指针在这里看起来像是纯粹的开销;它不提供任何基本或有用的间接级别。