CjR*_*bin 5 c address-sanitizer
我正在使用 C 和 pthreads 库开发多线程客户端,使用 boss/worker 架构设计,并且在理解/调试范围后堆栈使用错误时遇到问题,该错误导致我的客户端失败。(我对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
Run Code Online (Sandbox Code Playgroud)
我希望工作人员从队列中提取 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
Run Code Online (Sandbox Code Playgroud)
如果我们这样做,那么评论实际上就是事实。因为否则我们将创建work_item一个指向.Request_work_item
不幸的是,由于work_item具有类型void*,因此它可以以任何一种方式编译。
如果队列另一端的项目的使用者将其提取为 a 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.
Run Code Online (Sandbox Code Playgroud)
然后,消费者需要free该结构以及free指针。这个额外的指针在这里看起来像是纯粹的开销;它不提供任何必要或有用的间接级别。