2016-07-14 9 views
1

Ich habe zwei Funktionen 'refFunc' und 'valFunc' in zwei separaten .c-Dateien mit Header-Dateien geschrieben. Ich habe versucht, sie zusammen mit einer mex Wrapper-Funktion 'mainmex' zu kompilieren und sie zu einer ausführbaren mex-Datei zu verbinden. Die Funktion 'refFunc' nimmt ein 'int' und gibt diese Ganzzahl mit 2 multipliziert zurück. Die Funktion 'valFunc' macht dasselbe, nur ruft sie durch Referenz auf, anstatt nach Wert zu rufen, und sie gibt nichts zurück. 'valFunc' wird problemlos ausgeführt, aber 'refFunc' verursacht eine Zugriffsverletzung.Warum funktionieren Funktionen, die per Referenz aufrufen, nicht, wenn sie aus anderen Quelldateien in einem Mex-Wrapper verlinkt sind?

Als eine Überprüfung der Gesundheit, wiederholte ich die gleichen Schritte mit einem "Vanille" c Wrapper "Mainc". Die Funktion lief einwandfrei ohne Probleme. Gibt es in Matlab eine Eigenart, die das verursacht? Oder mache ich etwas falsch? Hier

ist der Code für mainmex.c

#include "mex.h" 
#include "valFunc.h" 
#include "refFunc.h" 
#include <stdio.h> 


void mexFunction(int nlhs, mxArray *plhs[], 
       int nrhs, const mxArray *prhs[]) 
{ 
    printf("executing valFunc, answer is %i\n", valFunc((int)5)); 
    int *b; 
    *b = 0; 
    printf("executing valFunc, ..."); 
    refFunc((int)5, b); 
    printf("b is %i\n", *b); 
} 

Und für refFunc.c

#include "refFunc.h" /*Doesn't seem to make a difference whether or not I 
        include the header file*/ 
void refFunc(int a, int *b) 
{ 
    *b = 2 * a; 
} 

Und für valFunc.c

#include "valFunc.h" /*Doesn't seem to make a difference whether or not I 
        include the header file*/ 
int valFunc(int a) 
{ 
    int b = a * 2; 
    return b; 
} 

Und für refFunc.h

void refFunc(int a, int *b); 

Und für valFunc.h

int valFunc(int a); 

Und für mainc.c

#include "valFunc.h" 
#include "refFunc.h" 
#include <stdio.h> 

void main() 
{ 
    printf("executing valFunc, answer is %i\n", valFunc((int)5)); 
    int *b; 
    *b = 0; 
    printf("executing valFunc, ..."); 
    refFunc((int)5, b); 
    printf("b is %i\n", *b); 
} 

Und schließlich bin mit dem Befehl, den ich zu kompilieren und die mex und die Ausgabe Ich habe

>> mex refFunc.c valFunc.c -c 
Building with 'MinGW Compiler (C)'. 
MEX completed successfully. 
>> mex mainmex.c refFunc.obj valFunc.obj 
Building with 'MinGW Compiler (C)'. 
MEX completed successfully. 
>> mainmex 
executing valFunc, answer is 10 
executing valFunc, ... 
------------------------------------------------------------------------ 
      Access violation detected at Thu 
laufen

Als ich zu Bash wechselte, habe ich Folgendes getan und bekam folgendes:

$ gcc mainc.c valFunc.obj refFunc.obj -fno-use-linker-plugin 
$ ./a.exe 
executing valFunc, answer is 10 
executing valFunc, ...b is 10 

Beachten Sie, wie ich sogar die gleichen .obj-Dateien verwendet habe, die von meiner Arbeit in Matlab übrig geblieben waren.

+0

Das hat nichts speziell mit Matlab oder Mex zu tun. Das ist genau die Einstellung, in der das Problem aufgetreten ist. Tags bearbeitet –

Antwort

1

mexFunc() deklariert einen Zeiger und kann nicht initialisiert werden. Der Wert dieses Zeigers ist unbestimmt. Sie geben dann diesen Zeiger an refFunc() weiter, der versucht, sein Ergebnis an den (unbestimmten) Speicherort zu schreiben, auf den der Zeiger zeigt. Dies zeigt undefiniertes Verhalten.

mexFunction() sollte diese stattdessen tun:

void mexFunction(int nlhs, mxArray *plhs[], 
       int nrhs, const mxArray *prhs[]) 
{ 
    int b;     // declare b as int, not int * 
    refFunc((int)5, &b);  // pass the address of b 
    printf("b is %i\n", b); // b's value has been set 
} 

Beachten Sie auch, dass C weder Referenzen als eine Vielzahl von Datentyp hat noch pass-by-reference Aufruf Semantik. Alle C-Funktionsaufrufe sind pass-by-value; In einigen Fällen wie diesem sind Argumente Zeiger (die als Wert übergeben werden).

+0

Arbeitete wie ein Charme. Danke für Ihre Antwort. –

+0

Tatsächlich deklariert er im ursprünglichen Code des OP den nicht initialisierten Zeiger b und versucht dann, ihn mit '* b = 0 zu dereferenzieren.« Dies könnte leicht direkt vor dem Aufruf von refFunc() abstürzen. – FredK

+0

Richtig bist du, @FredK.Ich habe meine Antwort aktualisiert, um die Situation genauer zu beschreiben, obwohl keine Änderung der empfohlenen Korrektur erforderlich ist. –