Hej jag har ett problem jag hoppas att jag kan få hjälp med.
Jag har ett trådat program med 2 trådar.
I den ena tråden skriver jag till en kö som är trådskyddad (bara 1 av trådarna kan utföra operationer i kön åt gången).
I kön sparar jag pekare till datan som man vill spara.
Alltså jag kör pekare = malloc() lägger in fyller minnet som pekaren pekar på. Lägger till pekaren till kön sedan avslutas funktionen.
I den andra tråden så hämtar jag ut pekaren. Kan ta hand om datan utan problem. MEN när jag väljer free(pekare) som jag fick av listan så frigörs inte minnet.
Jag har testat att både lägga in pekare och hämta ut pekare och frigöra direkt i samma tråd då fungerar det.
Men när jag gör exakt samma sak förutom att det görs i skilda trådar så frigörs inte minnet. Vad kan vara fel?
Jag hoppas att beskrivningen kan framge vad som kan vara fel då koden är riktigt stor.
PeWMedlem sedan juni 20006 839 inlägg Vad menar du med att minnet inte frigörs? Får du felmeddelanden eller vad? Genom att en trådning i samma process delar på samma minnesutrymme ska det inte ha nån betydelse vart i programmet man skapar och tar bort bokat utrymme på processheapen, så länge det sker i rätt ordning. Det här med trådat tillför ju lite extra att tänka på.. bl.a i vilken ordning saker och ting exekvererar. Har du synkat trådarna?
okej, saken är denna...
Kön fungerar följande..
När man skall hämta ett meddelande.. Är kön tom ja då används cond_wait (pthread).
När någon lägger in ett meddelande så anropas "signal" som säger till alla trådar med ett visst condition att kolla sin kö. Allt körs med mutex. Så bara en tråd kan hämta eller skriva samtidigt.
Saken är nu den att jag testade att skriva ut minnes referensen i tråd 1 som skriver och gör jag detta så är allt som det skall enligt task manager.
DP är av typen *DP en pekare gör jag detta så blir minnet helt okej- Men kommenterar jag bort printf:en så rensar den inte minnet.. Om jag byter till att bara skriva ut text med printfen så rensar den inte.
sendMessage(messageSenderMailBox[0], DP);
printf("Innan: %8x\n", (unsigned int) DP);
Då sparas en pekare i kön. För att göra det lättast möjligast på andra sida bara för debugging nu har jag tagit
free(waitForMessage(messageSenderMailBox[0] /*mailBox*/))
PeWMedlem sedan juni 20006 839 inlägg Öh.. jag tror inte jag fattar riktigt. Själva funktionen printf påverkar inte pekaren ö.h.t så slutsatsen att om du tar bort printf så rensas inte minnet måste vara fel. Men du skriver ju printf i ovan förklaring efter det att du skickat meddelandet. Om det blir ett avbrott mellan de två raderna så att exekverering av det övriga sker kommer printfen att skriva ut adressen till den raderade pekaren vilket isf kan leda till att man tror att det inte raderats - om man tittar på adresserna dvs. Jag kanske blandar ihop det med vad du menar? Ivf så har inte printf i sig med allokering av pekare att göra. Däremot kan ett sådant funktionsanrop påverka i vilken ordning trådarna exekvererar om de inte är synkade på rätt sätt (det finns utrymme för avbrott på ett kritiskt ställe), beroende på hur schemaläggaren jobbar. Det kanske är nåt knas med hur du hämtar meddelandet från din meddelandekö.. ligger hela rasket i samma skyddade sektion?
PeWMedlem sedan juni 20006 839 inlägg Såg att du redigerat in lite mer. Kan du inte (via pseudo om du så vill) visa förloppet lite mer strukturerat?
För att lägga in i min kö:
Denna kallar tråd 1 på och skickar in en pekare till något den kört malloc på.
void sendMessage( MailBox *mailBox , void *message ) {
assert( mailBox != NULL );
assert( message != NULL );
pthread_mutex_lock( &mailBox->mutex );
enqueue( mailBox->buffer , message );
pthread_cond_signal( &mailBox->condition );
pthread_mutex_unlock( &mailBox->mutex );
}
för att hämta ut:
Denna kallar tråd 2 på och får ut. Det den gör med den pekaren sedan tar den free() på. Men när jag kikar i Task manager så har inte den här free() någon betydelse.
Men skulle jag använda den här funktionen i samma tråd lika många gånger som jag lagt in det och tagit free på pekaren jag fått ut så rensas minnet som det skall.
void *waitForMessage( MailBox *mailBox ) {
pthread_mutex_lock( &mailBox->mutex );
void *data = dequeue( mailBox->buffer );
while ( data == NULL ) {
pthread_mutex_lock( &mailBox->mutex );
pthread_cond_wait( &mailBox->condition , &mailBox->mutex );
pthread_mutex_lock( &mailBox->mutex );
data = dequeue( mailBox->buffer );
}
pthread_mutex_unlock( &mailBox->mutex );
return data;
}
Problemet med printf kan eventuellt bero på ett synkroniseringsproblem. Ofta dyker fel upp när man tar bort debug-utskrifter, vilket beror på att I/O tar väldigt mycket tid och på så sätt "synkroniserar". Jag förstår inte heller riktigt koden i waitForMessage (jag har iofs inte använt phtreads). Blockerar inte pthread_mutex_lock( &mailBox->mutex ); tills låset är taget? I så fall behöver kön inte låsas igen bara för att den råkar vara tom. Det känns som ett fin möjlighet till deadlock. Ett ex.
void *waitForMessage( MailBox *mailBox ) {
pthread_mutex_lock( &mailBox->mutex );
void *data = dequeue( mailBox->buffer );
while ( data == NULL ) {
// Vänta tills någon signalerar att det finns data.
pthread_cond_wait( &mailBox->condition , &mailBox->mutex );
data = dequeue( mailBox->buffer );
}
pthread_mutex_unlock( &mailBox->mutex );
return data;
}
// PS. Antar att signal-and-continue används.
Men, som sagt, jag har inte använt pthreads så det kanske inte fungerar som jag tror.
Jag har nu hittat felet, det var inget fel :D.
Felet var att jag kom på att en process ger inte tillbaka minnet till operativsystemet utan bara till sin egen process så att den inte behöver allokera mer minne.