Null-Pointer in main()...



  • SeppJ schrieb:

    Er definiert vor dem Inklude per Makro "extern" zu "". Damit wird aus der Deklaration eine Definition. Und ich glaube, ich höre an der Stelle lieber auf mit der Analyse, sonst fang ich an vor Schmerz zu schreien.

    Aua.

    ~(ich hatte mir den Code noch unformatiert angesehen und erst später geantwortet)~



  • #include "stdafx.h"
    

    Schrott. Unnötige Abhängigkeiten.

    #define extern
    #undef extern
    

    Schrott. Standardheader sind tabu, und Schlüsselworte natürlich auch. Immer und überall.

    extern double** A;
    

    In Zusammenhang mit Mehrfachdimensionen immer Schrott weil UB.



  • Hi!

    Ich hab meine Dateien noch mal überarbeitet... ich kann mir die eingelesenen werte in dem main modul ausgeben lassen. manchmal... teilweise erhalte ich aber den im titel genannten fehler der dann die drei in der main funktion genutzten funktionen betrifft. manchmal geht es, dann wieder nicht. Ich arbeite mit visual studio, version 15.1. Durch googeln habe ich den eindruck gewonnen, es könnte mit der verknüpfung der verschiedenen dateien zu tun haben?!

    Ich schicke hier noch mal den aktuellen code. Über Hilfe würde ich mich freuen!

    Application.c:
    --------------

    #include "stdafx.h"
    #include <stdio.h>
    #include <stdlib.h>
    
    #include "ReadAlloc.h"
    
    int main()
    {
    
    	int nrow, ncol;
    	double **matrixFromText;
    
     //read nrow and ncol, then alloc matrix, then read matrix
    //////////////////////////////////////////////////////////
    	readNrowNcol(&nrow, &ncol);
    
    	matrixFromText = allocMatrix(nrow, ncol);
    
    	fillMatrix(matrixFromText, nrow, ncol);
    
    	//Test, ob einlesen funktioniert...
    	  printf("%d %d\n", nrow, ncol);
    	//printf("\n%f\n", matrixFromText[0][0]);
    	  printf("\n%f\n", matrixFromText[2][0]);
    	  getchar();
    ////////////////////////////////////////////////////////////
    
    	return 0;
    }
    

    ReadAlloc.c:
    ------------

    #include "ReadAlloc.h"
    
    extern int nrow, ncol;
    extern double **matrixFromText;
    
    void readNrowNcol(int *nrow, int *ncol)
    {
    	double temp;
    	FILE *fp;
    	fp = fopen("inputMatrix1.txt", "r");
    
    	if (fp == NULL)
    
    	{
    		puts("Fehler beim Oeffnen\n");
    		getchar();
    		exit(EXIT_FAILURE);
    	}
    
    	else
    
    		puts("erfolgreich geoeffnet!\n");
    
    	while (fgetc(fp) != ':')
    	{
    	}
    
    	fseek(fp, +1, SEEK_CUR);
    
    	fscanf(fp, "%d", nrow);
    	/*printf("%d\n", nrow);
    	getchar();*/
    
    	while (fgetc(fp) != ':')
    	{
    	}
    
    	fseek(fp, +1, SEEK_CUR);
    
    	fscanf(fp, "%d", ncol);
    
    }
    
    double **allocMatrix(int nrow, int ncol)
    {
    	int i;
    	double** Matrix;
    	Matrix = (double**)malloc((nrow) * sizeof(double *));
    	for (i = 0; i <= nrow; i++)
    	{
    		Matrix[i] = (double *)malloc((ncol) * sizeof(double));
    	}
    
    	return Matrix;
    
    }
    
    void fillMatrix(double **Matrix, int nrow, int ncol)
    {
    	int i, j;
    	double temp;
    	FILE *fp;
    	fp = fopen("inputMatrix1.txt", "r");
    
    	if (fp == NULL)
    
    	{
    		puts("Fehler beim Oeffnen\n");
    
    		exit(EXIT_FAILURE);
    	}
    
    	else
    
    		puts("erfolgreich geoeffnet!\n");
    
    	while (fgetc(fp) != '#')
    	{
    	}
    
    	fseek(fp, +1, SEEK_CUR);
    
    	for (i = 0; i <= nrow - 1; i++)
    	{
    		for (j = 0; j <= ncol - 1; j++)
    		{
    
    			fscanf(fp, "%lf", &temp);
    
    			if (feof(fp) && (i * j) < ((nrow - 1) * (ncol - 1)))
    			{
    				printf("ERROR zu wenig Elemente\n");
    				getchar();
    			}
    
    			Matrix[i][j] = temp;
    
    		}
    	}
    
    	fclose(fp);
    }
    

    ReadAlloc.h:
    ------------

    #pragma once
    #include "stdafx.h"
    #include <stdio.h>
    #include <stdlib.h>
    
    void readNrowNcol(int *nrow, int *ncol);[code]
    
    double **allocMatrix(int nrow, int ncol);
    
    void fillMatrix(double **Matrix, int nrow, int ncol);
    


  • Du musst alle benötigten .c Dateien in dein Project mit aufnehmen.

    Der C-Compiler macht das nicht für dich.



  • DirkB-mobil schrieb:

    Du musst alle benötigten .c Dateien in dein Project mit aufnehmen.

    Der C-Compiler macht das nicht für dich.

    danke für die Antwort! Wie denn? ich habe im ordner "Quelldateien" mithilfe des kontextmenüs c dateien hinzugefügt. Ich dachte (hatte gehofft), somit werden diese bestandteil des projekts und beim kompillieren nicht ignoriert...

    ich bin leider mit der microsoft hilfe nicht glücklich geworden, sonst würde ich nicht noch mal fragen...



  • Über das Project-Menu von Visual-Studio geht das.



  • stekuntze schrieb:

    Hi!

    ReadAlloc.c:
    ------------

    extern int nrow, ncol;
    extern double **matrixFromText;
    

    Was willst du mit diesen beiden extern -Zeilen bezwecken? Lösche beide Zeilen komplett! Du übergibst doch die Variablen als Parameter an die Funktionen.

    Zur Matrix: es ist häufig sinnvoller/einfacher, nur ein 1d-Feld der Länge rows*cols zu erzeugen und den entsprechenden Index von Hand zu berechnen (also z.B. row*cols+col oder col*rows+row - je nachdem, welches Layout du im RAM haben willst) anstatt hier eine 1d-Matrix mit double* zu erzeugen und dann jedem dieser pointer wieder eine 1d-Matrix zu erzeugen.



  • wob schrieb:

    stekuntze schrieb:

    Hi!

    ReadAlloc.c:
    ------------

    extern int nrow, ncol;
    extern double **matrixFromText;
    

    Was willst du mit diesen beiden extern -Zeilen bezwecken? Lösche beide Zeilen komplett! Du übergibst doch die Variablen als Parameter an die Funktionen.

    Zur Matrix: es ist häufig sinnvoller/einfacher, nur ein 1d-Feld der Länge rows*cols zu erzeugen und den entsprechenden Index von Hand zu berechnen (also z.B. row*cols+col oder col*rows+row - je nachdem, welches Layout du im RAM haben willst) anstatt hier eine 1d-Matrix mit double* zu erzeugen und dann jedem dieser pointer wieder eine 1d-Matrix zu erzeugen.

    War gestern mein erster Versuch, mal mit mehreren Dateien zu arbeiten. Ich hab jetzt nur noch lokal Variablen in der main() funktion im main modul. ich glaube, das soll auch ein guter style sein, auf globale variablen zu verzichten. ich habe mein programm zum laufen gebracht, nachdem ich meine header in so ne präprozessorabfrage gepackt hab, ob die schon mal kompilliert wurden oder so (hatte das in nem buch gesehen) a la:

    #ifndef XYZ
    #define XYZ
    
    void readNrowNcol(int *nrow, int *ncol);
    double **allocMatrix(int nrow, int ncol);
    void fillMatrix(double **Matrix, int nrow, int ncol);
    
    #endif //
    

    ich bin glücklich, dass es geht. wenn mir noch jemand etwas zu den hintergründen sagen kann, wäre schön 🙂

    der typ mit der matrix ist auch gut. vielleicht ändere ich das noch.



  • stekuntze schrieb:

    ich glaube, das soll auch ein guter style sein, auf globale variablen zu verzichten.

    wenn du mal zeit und lust hast, programmier mal ein größeres projekt (k.a. 2000 zeilen dürften reichen) und nimm nur globale variablen. danach (wenn du überhaupt so weit kommst) weißt du sozusagen aus 1. quelle, warum globale variablen so "böse" sind. 😃 aber manchmal gehts nicht anders.

    ich bin glücklich, dass es geht. wenn mir noch jemand etwas zu den hintergründen sagen kann, wäre schön 🙂

    manchmal musst du headerdateien an mehreren stellen einbringen und wenn dus geschickt programmierst, hast du dann ne endlosschleife.



  • Jede C-Datei wird vom Compiler als eine unabhängige Einheit übersetzt.
    Bei den #include -Zeilen wird die angegebene Datei eingefügt.
    Der Compiler macht daraus eine sog. Object-Datei (meist *.o oder *.obj)

    Wenn alle C-Dateien übersetzt sind, kommt der Linker und bindet diese Object-Dateien mit den Bibliotheken zu einer ausführbaren Datei (oft *.exe) zusammen.

    In den Objectdateien stehen auch noch die Namen der enthaltenen und benötigten Funktionen und (globalen) Variablen.

    Wenn da etwas fehlt, gibt es eine Fehlermeldung wie "error LNK2019: Verweis auf nicht aufgelöstes externes Symbol"
    Das LNK deutet auf den Linker, danach sollte auch noch das genaue Symbol (Name) des fehlenden Teils genannt werden.

    stekuntze schrieb:

    ich habe mein programm zum laufen gebracht, nachdem ich meine header in so ne präprozessorabfrage gepackt hab, ob die schon mal kompilliert wurden oder so (hatte das in nem buch gesehen) a la:

    Das sind sog. Include-Guards.

    Die sind dann wichtig, wenn du eine Header-Date (*.h) in einer anderen Header-Datei einbindest.
    In deinem Beispiel hast du stdio.h zweimal eingefügt.
    Einmal direkt mit #include <stdio.h>, dass zweite mal über #include "ReadAlloc.h"
    Das wird damit verhindert.


Anmelden zum Antworten