2012-05-27 10 views
5

Ho provato questo per ore, e google tutte le cose che penso gentilmente, ma sto diventando pazzo.Puntatori all'interno del segmento di memoria condivisa

Ho una struct:

typedef struct { 
    int rows; 
    int collumns; 
    int* mat; 
    char* IDs_row; 
} mem; 

Non conosco le dimensioni del int * (una matrice) e char * fino a tardi.

Quando lo faccio, creo la memoria condivisa in questo modo:

mem *ctrl; 
int size = (2 + ((i-1)*num_cons))*sizeof(int) + i*26*sizeof(char); //I have the real size now 
shmemid = shmget(KEY, size, IPC_CREAT | 0666); 
if (shmemid < 0) { 
    perror("Ha fallado la creacion de la memoria compartida."); 
    exit(1); 
} 
ctrl = (mem *)shmat(shmemid, 0, 0); 
if (ctrl <= (mem *)(0)) { 
    perror("Ha fallado el acceso a memoria compartida"); 
    exit(2); 
} 

Nessun problema qui. Poi do un valore a ctrl-> rows e collumns, e assegno 0 a tutta la matrice.

Ma dopo, scrivo qualcosa nel char * e bam, segmentation fault.

Debug del programma Ho visto che entrambi i puntatori, mat e IDs_row dove null. Come posso dare loro i valori corretti all'interno del segmento di memoria condivisa ??

Ho provato a rimuovere il puntatore char *, solo per provarlo, e quindi l'errore di errore di segmentazione era nell'altro programma collegato a detta memoria condivisa e ho controllato i valori all'interno della matrice (controllo -> righe e -> collumns era di successo)

risposta

5
ctrl = (mem *)shmat(shmemid, 0, 0); 

Questo assegna solo memoria valida al puntatore ctrl, non ctrl->mat o ctrl->IDs_row.

probabilmente si vuole:

mem *ctrl; 
shmemid = shmget(KEY, sizeof(ctrl), IPC_CREAT | 0666); 
//allocate memory for the structure 
ctrl = (mem *)shmat(shmemid, 0, 0); 

//allocate memory for the int* 
shmemid = shmget(KEY,((i-1)*num_cons))*sizeof(int), IPC_CREAT | 0666); 
ctrl->mat = (int*)shmat(shmemid, 0, 0); 

//allocate memory for the char* 
shmemid = shmget(KEY,i*26*sizeof(char), IPC_CREAT | 0666); 
ctrl->IDs_row = (char*)shmat(shmemid,0,0); 
+0

Grazie! Non avevo mai pensato di fare lo shmget per ogni puntatore. (Non capisco nemmeno come funziona, facendo la stessa chiamata ma "lanciandolo") Ora c'è un problema con il secondo intero nella struct, i "collumns". Ho messo un "1" lì in un unico processo, e l'altro processo lo legge come 62045 o qualcosa del genere. Ho provato a cambiare sizeof (ctrl) in sizeof (uomo) e 2 * sizeof (int) + sizeof (int *) + sizeof (char *), ma senza fortuna. – Knudow

+0

Siamo spiacenti, ho inviato il messaggio e poi modificato. Puoi aiutarmi un po 'di più? Ho un problema ora con il secondo numero intero nella struttura. – Knudow

+0

@ user1420534 si prega di inviare una nuova domanda con questo nuovo problema, non sembrano correlati. –

7

Prima di tutto, mettere assoluti puntatori in segmenti di memoria condivisa è pessima idea terible - quei puntatori sarebbe solo valida nel processo che ha riempito nei loro valori. I segmenti di memoria condivisa sono non garantito da allegare allo stesso indirizzo virtuale in ogni processo. Al contrario, allegano dove il sistema lo ritiene possibile quando shmaddr == NULL viene specificato alla chiamata a shmat(). È possibile specificare lo stesso indirizzo virtuale quando si chiama shmat() ma è compito dell'utente assicurarsi che nient'altro sia mappato su tale area di memoria in tutti i processi partecipanti di. Questo è difficile da fare in modo portatile. Quello che vorresti fare di più è:

1) Assegna un segmento di memoria condivisa che ospita sia la struttura mem sia i due array di dati. Quindi non si dovrebbero mettere i puntatori assoluti ma piuttosto i puntatori relativi all'inizio del blocco di memoria e quindi regolare l'utilizzo.

2) Assegnare tre diversi segmenti di memoria condivisa ma invece di mettere puntatori, mettere i ID memoria condivisa come restituito da shmget():

typedef struct { 
    int rows; 
    int collumns; 
    int mat_id; 
    int IDs_row_id; 
} mem; 

Quando si deve accedere alla matrice o array ID basta allegare all'ID memoria condivisa memorizzato nel campo corrispondente.

Prestare attenzione, tuttavia, che l'utilizzo dello stesso KEY in invocazioni successive di shmget() non produca il risultato previsto a meno che KEY == IPC_PRIVATE. È preferibile utilizzare un valore di chiave fissa per il blocco di memoria condivisa con il descrittore (di tipo mem) e IPC_PRIVATE per gli altri due blocchi di memoria altrimenti le tre chiamate restituiranno effettivamente lo stesso blocco di memoria condivisa - il primo sarà crealo e i prossimi due restituiranno semplicemente il suo ID poiché un blocco con quella chiave esiste già.

Problemi correlati