Понимание ошибки использования стека после области - PullRequest
0 голосов
/ 20 сентября 2019

Я работаю на многопоточном клиенте, использующем C и библиотеку pthreads, использующем архитектуру босса / рабочего, и у меня возникают проблемы с пониманием / отладкой ошибки стека использования после области действия, которая приводит к сбою моего клиента.(Я немного новичок в 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, и информации об этой ошибке в Интернете не так много, поэтому любые указатели будут с благодарностью.

1 Ответ

1 голос
/ 20 сентября 2019

Красный флаг здесь означает, что &request_ctx является адресом локальной переменной.Это не указатель на хранилище, выделенное с помощью malloc, а адрес переменной, которая содержит это хранилище.Эта переменная исчезает после завершения этой области действия, даже если срок действия блока malloc.

Возможно, исправление заключается в простом удалении оператора address-of & в этой строке?

steque_item work_item = &request_ctx; // steque_item is a void* so passing
                                      // it a pointer to the Request_work_item

Если мы сделаем это, то комментарий на самом деле говорит правду.Потому что в противном случае мы создаем work_item a указатель на указатель на 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 указатель.Этот дополнительный указатель здесь выглядит просто как накладные расходы;он не обеспечивает какого-либо существенного или полезного уровня косвенности.

...