2015-03-19 12 views
8

Sto cercando di usare MATLAB Coder per convertire il codice da Matlab in un file MEX. Se ho un frammento di codice della forma seguente:Come identificare i posti in MATLAB in cui i dati sono memorizzati al di fuori dei limiti di un array?

x = zeros(a,1) 
x(a+1) = 1 

poi in Matlab questo sarà ridimensionare la matrice per accogliere il nuovo elemento, mentre nella MEX file Questo darà un errore "Indice supera dimensioni della matrice". Mi aspetto che ci siano molti punti nel codice in cui ciò sta accadendo.

Quello che voglio fare è eseguire la versione MATLAB del codice (senza usare il codificatore) ma MATLAB genera un errore o un avviso ogni volta che ridimensiona un array perché assegno a qualcosa al di fuori dei limiti. (Potrei semplicemente usare il file MEX e vedere dove appaiono gli errori, ma questo richiede la ricostruzione dell'intero file MEX usando MATLAB Coder ogni volta che cambio del codice, che richiede un po 'di tempo.)

C'è un modo per fare questo? C'è qualche tipo di impostazione in MATLAB che disattiverà il "ridimensionamento automatico se si assegna a un indice fuori limite", o dare un avvertimento se questo accade?

+0

Interessante domanda. "_Automaticamente ridimensiona se assegni a un indice out-of-bounds" è una caratteristica essenziale di Matlab. Sembra difficile intercettare questo comportamento –

+0

Ti interessano solo le assegnazioni _single-dimension_, _single-index_? Cioè, il tuo codice può contenere qualcosa come 'x = zeri (a, 1) x (a + 1: a + 10) = 1;'? O 'x = zeri (a, b) x (a + 1, b) = 1;'? –

+0

Voglio quasi dire no a questo perché è possibile solo perché sento che alcuni dei principali strumenti di Matlab si basano su questa funzionalità .... –

risposta

2

EDIT:As of Matlab 2015b, Coder ha ora il controllo errore di runtime come opzione (dalle note di rilascio Matlab):

In R2015b, generate librerie autonome e gli eseguibili in grado di rilevare e correggere gli errori di runtime rapporto quali come indicizzazione di array fuori dai limiti. Nelle versioni precedenti di , solo MEX generato rilevava e riportava gli errori di esecuzione .

Per impostazione predefinita, il rilevamento degli errori in fase di esecuzione è abilitato per MEX. Con il valore predefinito di , il rilevamento degli errori di runtime è disabilitato per le librerie standalone e gli eseguibili.

Per attivare la rilevazione degli errori in fase di esecuzione per standalone librerie ed eseguibili:

Nella riga di comando, utilizzare la proprietà di configurazione del codice RuntimeChecks.

cfg = coder.config ('lib'); % o 'dll' o 'exe'

cfg.RuntimeChecks = true;

codegen -config CFG myfunction

Utilizzando l'applicazione MATLAB Coder, nelle impostazioni di generazione del progetto, sulla scheda Debug, selezionare controllo Genera controlli di errore run-time scatola.

Le librerie e gli eseguibili generati utilizzano fprintf per scrivere i messaggi di errore su stderr e interrompere la chiusura dell'applicazione. Se fprintf e abort non sono disponibili, è necessario fornirli. I messaggi di errore sono in inglese.

Vedere Run-Time Error Detection and Reporting in Standalone C/C++ Code e Generate Standalone Code That Detects and Reports Run-Time Errors.

risposta originale: La risposta nei commenti dichiarando una classe sottoclasse dal doppio in cui il metodo di subsref è sovraccarico per non consentire in crescita sarebbe un buon modo per farlo.

Un altro modo semplice per farlo è quello di cospargere i comandi assert in tutto il codice (in ciascuna iterazione del ciclo o nella parte inferiore di una funzione) per affermare che la dimensione non è aumentata rispetto alla dimensione allocata.

Per esempio, se si ha il codice in un formato di:

x = zeros(a,1) 
x(a+1) = 1 
... lots of other operations 

if coder.target('MATLAB') 
    assert(isequal(size(x), [a,1]), 'x has been indexed out of bounds') 
end 

questo sarebbe ti permettono di avere l'affermazione fallire se qualsiasi valore sono stati assegnati che si estendeva l'array.

Per rendere un po 'più ordinato, è possibile anche eseguire una funzione che limiti il ​​controllo di tutte le variabili che ti interessano, ancora avvolgendo l'istruzione coder.target se attorno ad essa. Quindi potresti spargere tutto questo nel tuo codice.

Non è elegante come sovraccaricare la doppia classe, ma d'altra parte non aggiunge alcun sovraccarico al codice compilato. Inoltre non ti darà errori esattamente quando avviene il sovraccarico, ma ti darà la sicurezza che il codice funzioni bene in una varietà di situazioni.

Un altro modo per essere più sicuri degli incarichi è eseguire i propri limiti controllando l'assegnazione in situazioni in cui ciò potrebbe essere appropriato. Un problema comune che ho visto nell'assegnazione è qualcosa di simile. Abbiamo una matrice allocata e stiamo copiando i dati da un'altra matrice con un'assegnazione di vettori. Per esempio, si consideri la seguente situazione:

t = char(zeros(5,7));    % Allocate a 5 by 7 char array 
tempstring = 'hello to anyone'; % Here's a string we want to put into it. 
t(1, 1:numel(tempstring)) = tempstring; % A valid assignment in MATLAB 

>> size(t) 
ans = 
5 15 

Uh oh, esattamente ciò che siete preoccupati per la questione è accaduto: la matrice t è stata ridimensionata automaticamente durante l'incarico, che opera in MATLAB, ma in Coder il codice creato causerà un errore segfault o MEX. Un'alternativa è quella di utilizzare la potenza della funzione end per mantenere l'assegnazione ordinata Se cambiamo il compito di (ma troncato.):

t(1,1:min(end,numel(tempstring))) = tempstring(1:size(t, 2)); 

Le dimensioni t rimarrà invariata, ma l'assegnazione verrà troncato. L'utilizzo di end consente il controllo dei limiti durante l'assegnazione. Per alcune situazioni, questo può essere un buon modo per gestire il problema e ti darà la certezza che i limiti non saranno mai superati, ma ovviamente in alcune situazioni questo è molto indesiderabile (e non ti darà messaggi di errore in MATLAB.)

Un altro utile strumento fornito da MATLAB è nell'editor stesso. Se si utilizza il tag %#codegen nel codice, verrà segnalato il correttore della sintassi dell'editor per evidenziare vari problemi di generazione del codice, inclusi i luoghi in cui si sta ovviamente aumentando la dimensione di un array mediante l'indicizzazione. Questo non può catturare ogni situazione, ma è un buon aiuto.

Editor example with codegen

Un'ultima nota. Come menzionato nella domanda, un file MEX generato da Coder ti darà un errore "Indice supera le dimensioni della matrice" proprio al momento dell'assegnazione e uscirà con grazia e ti dirà anche la riga di codice originale in cui si è verificato l'errore. Una libreria C generata da Coder non ha un buon comportamento o limiti di controllo e sarà completamente segfault senza diagnostica.La risposta intermedia è fare esattamente quello che stai facendo, cioè eseguire il codice come MEX. Non è molto utile alla tua domanda (come dici tu, ricostruire il MEX può richiedere del tempo), ma per quelli di noi che codificano per il mondo freddo e crudele del codice C esterno, il test intermedio di essere in grado di eseguire il MEX per trovare questi errori sono un vero toccasana.

La linea di fondo è che si tratta di una divergenza di comportamento tra MATLAB e codice C generato da Coder e può essere una fonte di problemi significativi. Nel mio codice, sono molto attento all'accesso agli array e alla crescita proprio per questo motivo. È un'area in cui mi piacerebbe vedere miglioramenti nello strumento Coder stesso, ma ci sono modi per fare molta attenzione quando si scrive codice MATLAB destinato a Coder.

Problemi correlati