2011-10-04 12 views
5

Questa potrebbe essere una domanda per principianti, ma voglio evitare l'overflow del buffer. Ho letto moltissimi dati dal registro che verranno caricati su un database SQL. Ho letto i dati in un ciclo e i dati sono stati inseriti dopo ogni ciclo. Il mio problema è che in questo modo, se leggo 20 chiavi, e i valori sotto sono (il numero di chiavi è diverso su ogni computer), quindi devo connettermi al database SQL 20 volte.Come gestire correttamente una stringa enorme?

Tuttavia ho scoperto che esiste un modo per creare una stored procedure e passare l'intero dato, e così, il server SQL si occuperà dei dati e devo collegarmi solo una volta al server SQL .

Purtroppo non so come gestire una stringa così grande per evitare errori imprevisti, come buffer owerflow. Quindi la mia domanda è come dovrei dichiarare questa stringa?

Dovrei semplicemente creare una stringa come char string[ 15000 ]; e concatenare i valori? O c'è un modo più semplice per farlo?

Grazie!

+6

sarebbe utile se sapevamo che il linguaggio di programmazione che si sta utilizzando, C o C++ –

+0

@ Rob:. sto utilizzando C, ma se qualcuno si presenta ad esempio un C++, quindi posso usarlo troppo – kampi

+4

non Perché solo fare più query di inserimento con una connessione? – Dmitri

risposta

2

Le stringhe STL dovrebbero svolgere un lavoro molto migliore rispetto all'approccio che hai descritto.

È inoltre necessario creare alcune soglie. Ad esempio, se la stringa è cresciuta più di un mega byte, sarà opportuno prendere in considerazione connessioni SQL diverse poiché la transazione sarà troppo lunga.

+1

Si noti inoltre che le stringhe della libreria C++ standard sono solo C++, non C. La libreria fornita con le implementazioni C++ è la libreria standard C++, _non_ l'STL. –

+0

Mooing Duck: potàto di patate, almeno in questo caso ('std :: string'). 'STL' può ancora essere usato in modo non ambiguo per riferirsi a quella parte della libreria C++ Standard che era originariamente conosciuta come STL e successivamente incorporata nella libreria Standard. – rubenvb

0

Per fare ciò correttamente in C è necessario allocare la memoria in modo dinamico, utilizzando malloc o uno degli equivalenti del sistema operativo. L'idea qui è di capire quanta memoria hai effettivamente bisogno e quindi allocare l'importo corretto. Le funzioni di registro forniscono vari modi per determinare la quantità di memoria necessaria per ogni lettura.

Diventa un po 'più complicato se stai leggendo più valori e concatenandoli. Un approccio sarebbe quello di leggere ogni valore in un blocco di memoria assegnato separatamente, quindi concatenarli a un nuovo blocco di memoria una volta che li hai tutti.

Tuttavia, potrebbe non essere necessario risolvere questo problema. Se puoi dire "se i dati sono più di X byte il programma fallirà", puoi semplicemente creare un buffer statico come suggerisci. Assicurati solo di fornire le funzioni di concatenazione del registro e/o delle stringhe con le dimensioni corrette per la parte restante del buffer e controlla gli errori, in modo che se fallisce fallisce correttamente piuttosto che crash.

Un'altra nota: char buf[15000]; è OK se la dichiarazione è in ambito programma, ma se appare in una funzione è necessario aggiungere l'identificatore static. La memoria allocata in modo implicito in una funzione viene prelevata di default dallo stack, pertanto è probabile che una grande allocazione fallisca e blocchi il programma. (Quindicimila byte dovrebbero essere ok, ma non è una buona abitudine per entrare.)

Inoltre, è preferibile definire una macro per la dimensione del buffer, e utilizzare in modo coerente:

#define BUFFER_SIZE 15000 
char buf[BUFFER_SIZE]; 

in modo che tu possa facilmente aumentare la dimensione del buffer in seguito modificando una singola riga.

+0

Ho modificato la tua risposta un po '. I nomi macro sono convenzionalmente tutti maiuscoli quindi si distinguono. E 'stringa' non è un nome molto buono per un oggetto; L'ho cambiato in 'buf'. –

+0

@Keith, ho usato string [] perché era quello che l'OP usava nella sua domanda, ma non importa. Grazie per aver catturato il nome macro in minuscolo, dovevo essere ancora mezzo addormentato. –

0

È possibile leggere (chiave, valore) le coppie da un registro e archiviarle in un buffer preallocato mentre è presente spazio sufficiente. Mantenere la posizione di "scrittura" all'interno del buffer. Potresti usarlo per controllare se c'è spazio sufficiente per la nuova chiave, coppia di valori nel buffer. Quando non c'è spazio per la nuova coppia (chiave, valore) - eseguire la stored procedure e ripristinare la posizione di "scrittura" all'interno del buffer. Alla fine del ciclo "read key, value pairs" - controlla la posizione di "scrittura" del buffer ed esegue la stored procedure se è maggiore di 0. In questo modo si riduce al minimo il numero di volte che si esegue la stored procedure su un server.

const int MAX_BUFFER_SIZE = 15000; 
char buffer[MAX_BUFFER_SIZE]; 
char buffer_pos = 0; // "write" position within the buffer. 

... 

// Retrieve key, value pairs and push them into the buffer. 
while(get_next_key_value(key, value)) { 
    post(key, value); 
} 

// Execute stored procedure if buffer is not empty. 
if(buffer_pos > 0) { 
    exec_stored_procedure(buffer); 
} 
... 

bool post(const char* key, const char* value) 
{ 
    int len = strlen(key) + strlen(value) + <length of separators>; 

    // Execute stored procedure if there is no space for new key/value pair. 
    if(len + buffer_pos >= MAX_BUFFER_SIZE) { 
    exec_stored_procedure(buffer); 
    buffer_pos = 0; // Reset "write" position. 
    } 

    // Copy key, value pair to the buffer if there is sufficient space. 
    if(len + buffer_pos < MAX_BUFFER_SIZE) { 
    <copy key, value to the buffer, starting from "write" position> 
    buffer_pos += len; // Adjust "write" position. 
    return true; 
    } 
    else { 
    return false; 
    } 
} 

bool exec_stored_procedure(const char* buf) 
{ 
    <connect to SQL database and execute stored procedure.> 
} 
Problemi correlati