Malloc segmentation fault

Hier ist das Stück code in dem "segmentation fault" Auftritt (perror wird nicht genannt):

job = malloc(sizeof(task_t));
if(job == NULL)
    perror("malloc");

Um genauer zu sein, gdb sagt, dass die segfault geschieht innerhalb eines __int_malloc - call, das ist eine sub-routine Aufruf von malloc.

Da die malloc-Funktion aufgerufen wird, parallel zu anderen threads, anfangs dachte ich, es könnte das problem sein.
Ich war mit version 2.19 glibc.

Datenstrukturen:

typedef struct rv_thread thread_wrapper_t;

typedef struct future
{
  pthread_cond_t wait;
  pthread_mutex_t mutex;
  long completed;
} future_t;

typedef struct task
{
  future_t * f;
  void * data;
  void *
  (*fun)(thread_wrapper_t *, void *);
} task_t;

typedef struct
{
  queue_t * queue;
} pool_worker_t;

typedef struct
{
  task_t * t;
} sfuture_t;

struct rv_thread
{
  pool_worker_t * pool;
};

Nun die künftige Umsetzung:

future_t *
create_future()
{
  future_t * new_f = malloc(sizeof(future_t));
  if(new_f == NULL)
    perror("malloc");
  new_f->completed = 0;
  pthread_mutex_init(&(new_f->mutex), NULL);
  pthread_cond_init(&(new_f->wait), NULL);
  return new_f;
}

int
wait_future(future_t * f)
{
  pthread_mutex_lock(&(f->mutex));
  while (!f->completed)
    {
      pthread_cond_wait(&(f->wait),&(f->mutex));
    }
  pthread_mutex_unlock(&(f->mutex));
  return 0;
}

void
complete(future_t * f)
{
  pthread_mutex_lock(&(f->mutex));
  f->completed = 1;
  pthread_mutex_unlock(&(f->mutex));
  pthread_cond_broadcast(&(f->wait));
}

Den thread-pool selbst:

pool_worker_t *
create_work_pool(int threads)
{
  pool_worker_t * new_p = malloc(sizeof(pool_worker_t));
  if(new_p == NULL)
    perror("malloc");
  threads = 1;
  new_p->queue = create_queue();
  int i;
  for (i = 0; i < threads; i++){
    thread_wrapper_t * w = malloc(sizeof(thread_wrapper_t));
    if(w == NULL)
      perror("malloc");
    w->pool = new_p;
    pthread_t n;
    pthread_create(&n, NULL, work, w);
  }
  return new_p;
}

task_t *
try_get_new_task(thread_wrapper_t * thr)
{
  task_t * t = NULL;
  try_dequeue(thr->pool->queue, t);
  return t;
}

void
submit_job(pool_worker_t * p, task_t * t)
{
  enqueue(p->queue, t);
}

void *
work(void * data)
{
  thread_wrapper_t * thr = (thread_wrapper_t *) data;
  while (1){
    task_t * t = NULL;
    while ((t = (task_t *) try_get_new_task(thr)) == NULL);
    future_t * f = t->f;
    (*(t->fun))(thr,t->data);
    complete(f);
  }
  pthread_exit(NULL);
}

Und schließlich die Aufgabe.c:

pool_worker_t *
create_tpool()
{
  return (create_work_pool(8));
}

sfuture_t *
async(pool_worker_t * p, thread_wrapper_t * thr, void *
(*fun)(thread_wrapper_t *, void *), void * data)
{
  task_t * job = NULL;
  job = malloc(sizeof(task_t));
  if(job == NULL)
    perror("malloc");
  job->data = data;
  job->fun = fun;
  job->f = create_future();
  submit_job(p, job);
  sfuture_t * new_t = malloc(sizeof(sfuture_t));
  if(new_t == NULL)
    perror("malloc");
  new_t->t = job;
  return (new_t);
}

void
mywait(thread_wrapper_t * thr, sfuture_t * sf)
{
  if (sf == NULL)
    return;
  if (thr != NULL)
    {
      while (!sf->t->f->completed)
        {
          task_t * t_n = try_get_new_task(thr);
          if (t_n != NULL)
            {
          future_t * f = t_n->f;
          (*(t_n->fun))(thr,t_n->data);
          complete(f);
            }
        }
      return;
    }
  wait_future(sf->t->f);
  return ;
}

Den Warteschlange ist die lfds lock-free queue.

#define enqueue(q,t) {                                 \
    if(!lfds611_queue_enqueue(q->lq, t))             \
      {                                               \
        lfds611_queue_guaranteed_enqueue(q->lq, t);  \
      }                                               \
  }

#define try_dequeue(q,t) {                            \
    lfds611_queue_dequeue(q->lq, &t);               \
  }

Das problem passiert immer dann, wenn die Anzahl der Aufrufe async ist sehr hoch.

Valgrind-Ausgabe:

Process terminating with default action of signal 11 (SIGSEGV)
==12022==  Bad permissions for mapped region at address 0x5AF9FF8
==12022==    at 0x4C28737: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
  • Ist es möglich, etwas anderes vermasselt die Buchhaltung für malloc ?
  • Es klingt wie Speicher beschädigt woanders.
  • Es ist die einzige Erklärung, poste ich den ganzen code. (Es ist wirklich ein minimales Modell, mit memory leaks, etc.).
  • "wenn nötig, ich kann hier den vollständigen source code" - ja, das ist wahrscheinlich das, was Sie tun SOLLTEN, denn das Stück code oben selbst kann nicht bedeuten, die Quelle der segfault.
  • ok, fertig (dauerte einige Zeit damit, die 4 Felder überall, aber dann fand ich heraus, das mit Strg+k Abkürzung 🙂 )
  • ist dieser code reicht? Da kann ich alle code, einschließlich der beispielsweise im Betrieb, und die Warteschlange, die ich verwende. Die Warteschlange, die ich benutze ist von lfds lib und das Beispiel ist eine einfache fibonaci, die spawns zwei Aufgaben und wartet, für Sie).
  • Ich weiß nicht, was try_deque ist, aber es scheint, Sie sollten senden einen Zeiger an einen Zeiger try_dequeue(thr->pool->queue, &t); wie diese.
  • die try_dequeue gibt eine Aufgabe. der code, den ich gesetzt habe, funktioniert, für kleine Berechnungen, aber für die großen ist, wo die Probleme beginnen
  • Es nichts zurückgibt, ist es wohl gemeint-zu-Punkt t einer Aufgabe. Es können nicht tun, wenn Sie Sie senden eine Kopie des Zeigers.
  • Ich habe aktualisiert die post, um Sie zu beantworten. Ich weiß, es ist komisch, der Weg im Moment, es zu tun.
  • in das makro, wo ich die &t, obwohl ich nicht sollte)
  • Okay, ich sehe.
  • Andere erwähnt haben heap-Beschädigung, - das heißt, schreiben-vorbei-Ende Fehler, etc. Sie könnten in Erwägung ziehen, die glibc-Einrichtungen wie heap-überprüfung mit mcheck / mprobe.
  • Danke, ich werde versuchen, dass.
  • Keine chance, das Programm läuft unter valgrind? Wenn der Speicher Korruption vorgeht, valgrind könnte in der Lage sein, Ihnen zu zeigen, wo und Wann.
  • Sorry, ich habe die Ausgabe in der questoin.
  • Könnte das ein bug in malloc?
  • Ich denke nicht, aber es ist wahrscheinlicher als ein Fehler in malloc
  • Sorry, nur um sicher sein, dass wir testen, der gleiche code.. kann man kommentieren, enqueue(p->queue, t); try_dequeue(thr->pool>queue, t); e new_p->queue = create_queue() ? Tut es immer noch crash?
  • ich kann nicht coment es aus, ohne zu ändern das Ziel dieses Programms. Aber wenn Sie wollen, kann ich Ihnen den vollständigen Quellcode, einschließlich der wichtigsten, das Makefile, und so weiter, so können Sie vollständig zu testen. (Alles ist hier einfach viel zu viel, und ich würde wahrscheinlich vorstellen viel Verwirrung ich wer sonst liest diesen post). Was die enqueue-und try_dequeue tun ist, setzen Sie eine Aufgabe in die Globale Warteschlange des Pools und de try_dequeue bekommt eine Aufgabe aus der globalen Warteschlange des Pools.
  • Ich wird vergangenen hier code für Sie vor. Dies versuchen.
  • Ich klebte den code hier unten, versuchen Sie das zuerst, wenn es nicht hilft, kann ich Ihnen helfen, Ihren code Debuggen.
  • Danke, aber das hilft mir nicht viel, da das problem nur Auftritt, nachdem eine Menge von anrufen, die an die malloc-Betrieb
  • Ich sah ähnliches Problem bei Beendigung des Prozesses, wenn der main-thread ist schon fertig, aber einige worker-threads sind noch fortsetzen -, dass dies geschieht, weil der heap ist schon zerstört

InformationsquelleAutor guilhermemtr | 2014-02-26
Schreibe einen Kommentar