"Objektbasiertes C" Speicherzugriffsfehler

OP #4309516
Lesenswert?

Guten Tag,

ich muss mich im Moment mit "Objektbasiertem C" auseinandersetzen und 
habe so meine Probleme.

Kurze Info vorab ich muss das im Anhang zu findende Klassendiagramm 
programmieren.

Ich habe einen kleinen Teil versucht umzusetzen und bekomme einen 
Speicherzugriffsfehler beim ausführen.

Hier die main.c
1
#include "LED.h"
2
#include "PWMLed.h"
3
#include <stdio.h>
4
#include <stdlib.h>
5

6

7
int main()
8
{
9

10
  class_LED led1 = NewClassLed(1);  // Led Status zum Anfang 1
11

12
  printf("LED ist %d\n", led1->getStatus(led1));
13

14
free(led1);
15

16
return 0;
17
}

Hier erstelle ich eine LED und möchte ihren Status einfach nur ausgeben.

1
#ifndef LED_H_
2
#define LED_H_
3

4
typedef struct Led *class_LED;
5
 struct Led{  
6
  int (*getStatus)(class_LED led);
7
  int status;
8
};
9

10
class_LED NewClassLed(int status);
11

12
int getstatus(class_LED led);
13

14
#endif /* LED_H_ */

Die Header-Datei..
1
#include "LED.h"
2
#include <stdio.h>
3
#include <stdlib.h>
4

5

6
class_LED NewClassLed(int status)
7
{
8

9
  class_LED led = (struct Led*)malloc(sizeof(struct Led));
10
  led->status=status;
11

12

13
 return led;
14
}
15

16
int getstatus(class_LED led){
17
  int status = led->status;
18
  return status;
19
}

Und die LED.c


Ich sehe den Fehler nicht und wäre sehr dankbar für jegliche Hilfe.

Grüße

pat_w
Angehängte Dateien:
OP #4309570
Lesenswert?

Nase schrieb:
> Patti W. schrieb:
>> ich muss das im Anhang zu findende Klassendiagramm
>> programmieren
>
> "Ich muss" heißt doch sicher, dass du gerade eine Vorlesung besuchst
> oder anderweitig mehr zum Thema weißt oder...?

Jain, sitze zu Hause und versuche Stoff auszubereiten, da der Prof sagen 
wir keine "Ich bin dein Freund Haltung" besitzt und auf solche Fragen 
ehr entblößt reagiert. Nett formuliert.

Deshalb wäre ich eurer Hilfe hier sehr dankbar.
Gast #4309622
Lesenswert?

Ich würde dir aber wegen der Übersichtlichkeit vorschlagen dass du eine 
new Funktion wie in C++ implementierst, die dir einfach nur Speicher 
reserviert und von der Klasse den Konstruktor aufruft, dadurch wird das 
Anlegen von Klassen vereinheitlicht.

Ich hab im Internet vor einiger zeit mal einen Code gefunden indem dass 
so implementiert war, das ging irgendwie mit Virtuellen Tabellen, also 
alles in etwa so wie es auch der C++ Compiler macht. Da war dann auch 
Polymorphie möglich usw.
OP #4309670
Lesenswert?

Peter K. schrieb:
> Ich würde dir aber wegen der Übersichtlichkeit vorschlagen dass du eine
> new Funktion wie in C++ implementierst, die dir einfach nur Speicher
> reserviert und von der Klasse den Konstruktor aufruft, dadurch wird das
> Anlegen von Klassen vereinheitlicht.
>
> Ich hab im Internet vor einiger zeit mal einen Code gefunden indem dass
> so implementiert war, das ging irgendwie mit Virtuellen Tabellen, also
> alles in etwa so wie es auch der C++ Compiler macht. Da war dann auch
> Polymorphie möglich usw.

Klingt gut. Ich werde nachher für ein RaspberryPi Projekt eine 
"Einparkhilfe" mit dieser OOP realisieren müssen und werde mir deinen 
Tipp da zu Gemüt führen. Danke
Gast #4309674
Lesenswert?

du definierst hier:

class_LED led1 = NewClassLed(1);  // Led Status zum Anfang 1

die variavble led1 statisch und resevierst deren Speicherplatz nicht mit 
malloc() oder new() daher ist die freigabe des Speichers mit

free(led1);

nicht nur unötig sondern schädlich. das dürfte die zeile sein, die den 
speicherzugriffsfehler verursacht. Speicherplatz statisch vereinbarter 
variablen wird automatisch freigegeben, wenn der gültigkeitsbereich der 
variable verlassen wird.
Gast #4309699
Lesenswert?

Clemens L. schrieb:
> Wie man sieht, wird die Verständlichkeit durch das Verstecken des
> Zeigers in einem typedef nur verringert. "struct Led *" wäre nun auch
> nicht viel weniger Tipparbeit.

Da stimme ich dir zu dass das Verstecken eines Zeigers in einem Typedef 
nicht günstig ist, aber bensonders beim Objektorientierten zu 
Programmieren wird das oft gemacht weil man damit den Eindruck 
vermitteln möchte es handelt sich um das Objekt und nicht um einen 
Zeiger auf das Objekt.
Dann definiert man noch eine delete Funktion und es sieht aus wie C++.
Gast #4309704
Lesenswert?

Warum man nicht einfach direkt C++ verwendet ist schleierhaft... Da 
könnte man direkt gebraucht von schönen Dingen wie shared_ptr oder 
unique_ptr machen, sodass man zwar dynamischen Speicher verwenden, aber 
das Freigeben ("delete") gar nicht mehr vergessen kann!
Gast #4309719
Lesenswert?

Programmierer schrieb:
> Warum man nicht einfach direkt C++ verwendet ist schleierhaft...

C++ ist einfach für viele ein Rotes Tuch, siehe Linus Torvald. 
Andererseits war es früher auch so dass die ersten C++ Compiler einfach 
nur Übersetzer auf C Code waren und dieser wurde dann kompiliert.

Zudem ist es oft von Vorteil C zu verwenden wenn man wert auf 
Binärkompatibilität legt. C++ hat nämlich keine definierte ABI
#4309914
Lesenswert?

Das malloc in NewClassLed könnte auch null livern. Ein constructor soll 
Initialisieren, nicht Speicher reservieren. Ich würde dass so 
schreiben*:
1
void Led_init(struct* Led led, int status){
2
  led->status=status;
3
}
4

5
int Led_getStatus(struct Led* led){
6
  return led->status;
7
}
8

9
int main(){
10
  struct Led led;
11

12
  Led_init( &led, 1 );  // Led Status zum Anfang 1
13

14
  printf("LED ist %d\n", Led_getStatus(&led1));
15

16
  return 0;
17
}

* zumindest wenn ich nicht zu faul wäre und statdessen auf den getter 
verzichten und die Init methode durch einen designated initializer 
ersetzen würde.
Gast #4310072
Lesenswert?

Peter K. schrieb:
> Zudem ist es oft von Vorteil C zu verwenden wenn man wert auf
> Binärkompatibilität legt. C++ hat nämlich keine definierte ABI

Das ABI ist doch auch in C nicht im Standard geregelt, sondern in der 
Compilerdoku.
Msvc ist nicht binärkompatibel zu gcc.

Wo ist der Unterschied zu C++?
Gast #4310133
Lesenswert?

bal schrieb:
> Wo ist der Unterschied zu C++?

Naja beim C++ sind Programme die mit unterschiedlichen Compilerflags 
programmiert wurden oder die von zwei unterschiedlichen Versionen des 
selben Compilers kompiliert wurden nicht binärkompatibel.
Das ist auch der Grund warum viele C++ Programm ein Pluginsystem in C 
haben weil einfach dadurch ein Einheitliches Interface gibt.
Btw ich habe ein in C++ geschriebenes Programm mit C Pluginsystem, 
kompiliert mittels g++ und Plugins die ich mit dem Msvc kompiliert habe 
und das Funktioniert Problemlos.

Bei einem Pluginsystem in C++ funktionierte das nicht.

http://gcc.gnu.org/onlinedocs/gcc/Compatibility.html
Most platforms have a well-defined ABI that covers C code, but ABIs that 
cover C++ functionality are not yet common.
#4310292
Lesenswert?

Peter K. schrieb:
> bal schrieb:
>> Wo ist der Unterschied zu C++?
>
> Naja beim C++ sind Programme die mit unterschiedlichen Compilerflags
> programmiert wurden oder die von zwei unterschiedlichen Versionen des
> selben Compilers kompiliert wurden nicht binärkompatibel.

Das ist in C ganz genau gleich.
Sie können oder können nicht binärkompatibel sein. Welches davon der 
Fall ist bestimmt der Compilerhersteller.

> http://gcc.gnu.org/onlinedocs/gcc/Compatibility.html
> Most platforms have a well-defined ABI that covers C code, but ABIs that
> cover C++ functionality are not yet common.

Anders rum wird ein Schuh daraus.
Nicht C hat ein einheitliches ABI, sondern die zugrundeliegenden 
Betriebssysteme definieren durch ihre Programmierschnittstellen ein ABI. 
Da ein Betriebssystem aber nicht davon ausgehen kann, dass ein in C++ 
geschriebenes Programm auf ihm läuft, müssen diese ABI naturgemäss am 
kleinsten gemeinsamen Nenner ansetzen. Auf einer VAX war es problemlos 
möglich, von Fortran aus Lisp Code aufzurufen. Das hat aber nichts mit 
den definierten Eigenschaften von Fortran oder Lisp zu tun, sondern 
damit, das DEC für sich entschieden hat, in allen Sprachen einheitliche 
Schnittstellen auf Binärcode Ebene zu benutzen. Deshalb konnte man von 
Pascal auch PL/I Code aufrufen, der eine Fortran Subroutine zur 
Berechnung eines Problems benutzt, das mit Lisp optimiert wurde.
Gast #4310617
Lesenswert?

Karl H. schrieb:
> Nicht C hat ein einheitliches ABI, sondern die zugrundeliegenden
> Betriebssysteme definieren durch ihre Programmierschnittstellen ein ABI.

Wieder mal was dazu gelernt ;)

Worauf ich aber eigentlich raus wollte es gibt durchaus noch Gründe 
warum man in C Objektorientiert programmiert und nicht einfach C++ 
nimmt. Wobei in diesem Fall ist es vermutlich nur eine Übung um zu 
zeigen obwohl C Prozedural ist kann ich Objektrorientiert arbeiten wenn 
man möchte.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren