Hypercell ein ] Hypercell aus ] Zeige Navigation ] Verstecke Navigation ]
c++.de  
   
Forentreff 2012     
Bücher-Shop mit Amazon (Buchkategorien)C++ : Referenzen zu C++ : C++ Builder : Visual C++ : C# : Java : Spieleprogrammierung : Systemprogrammierung Linux : Software-Entwicklung : .NET : Compilertechnik : Algorithmen & Datenstrukturen : Objektorientierung : Entwurfsmuster : UML : eXtreme Programming : Scrum : Projektmanagement : Software-Testing : Datenbanken : Tom DeMarco : Dilbert : User Friendly
C/C++ Forum :: Projekt: OS-Development  ::  C vs C++ bei OSDEV     Zeige alle Beiträge auf einer Seite Auf Beitrag antworten
Autor Nachricht
abc.w
Mitglied

Benutzerprofil
Anmeldungsdatum: 25.04.2008
Beiträge: 1364
Beitrag abc.w Mitglied 20:36:07 30.01.2010   Titel:              Zitieren

Erhard Henkes schrieb:
Es gibt leider auch viele Punkte, die man nur instinktiv richtig machen kann, z.B. C anstelle C++ verwenden

Vorsicht, Vorsicht... ;)

Habe neulich meinen älteren Code rausgekrammt und siehe da, so schlecht ist C++ nicht...

C/C++ Code:
1
2
3
4
5
6
7
8
9
1
2
3
4
5
6
7
8
9
    CScreen stdout;
    CCpu CPU(0u);

    stdout << "Started.\n";

    ...

    CPU.DisableInterrupts();
    CPU.Halt();
C/C++ Code:
1
2
3
4
5
6
7
8
9
CScreen stdout;
CCpu CPU(0u);

stdout << "Started.\n";

...

CPU.DisableInterrupts();
CPU.Halt();
C/C++ Code:
1
2
3
4
5
6
7
8
9
    CScreen stdout;
    CCpu CPU(0u);

    stdout << "Started.\n";

    ...

    CPU.DisableInterrupts();
    CPU.Halt();
Erhard Henkes
Mitglied

Benutzerprofil
Anmeldungsdatum: 25.04.2000
Beiträge: 11924
Beitrag Erhard Henkes Mitglied 22:57:10 30.01.2010   Titel:              Zitieren

Die Idee der Klasse mit ihren "domestizierten" Funktionen ist hervorragend. Da hat C nur die Struktur mit "freien" Funktionen zu bieten. Das bezahlt man in C++ mit viel Klassenbeziehungs-Wirrwarr und im kernel nutzlosen Overhead.

_________________
OS-Development-, C++, Win32-API-, MFC-, Chemie-, Robotik- und Flugsimulator-Tutorials
http://www.henkessoft.de/index.htm
Tobiking2
Mitglied

Benutzerprofil
Anmeldungsdatum: 12.04.2009
Beiträge: 705
Beitrag Tobiking2 Mitglied 00:04:34 31.01.2010   Titel:              Zitieren

Erhard Henkes schrieb:
Die Idee der Klasse mit ihren "domestizierten" Funktionen ist hervorragend. Da hat C nur die Struktur mit "freien" Funktionen zu bieten. Das bezahlt man in C++ mit viel Klassenbeziehungs-Wirrwarr und im kernel nutzlosen Overhead.

Nur weil man C++ benutzt wird man aber nicht gezwungen komplizierte Klassenbeziehungen zu bauen oder Techniken zu nutzen die Overhead erzeugen. Und nutzlos ist es sicherlich nicht, selbst wenn es nur didaktischen Zwecken dient. :D
Erhard Henkes
Mitglied

Benutzerprofil
Anmeldungsdatum: 25.04.2000
Beiträge: 11924
Beitrag Erhard Henkes Mitglied 00:21:34 31.01.2010   Titel:              Zitieren

Zeige mir eine konkrete Stelle in PrettyOS im Kernel, bei der uns C++ einen greifbaren Vorteil bringen würde.

_________________
OS-Development-, C++, Win32-API-, MFC-, Chemie-, Robotik- und Flugsimulator-Tutorials
http://www.henkessoft.de/index.htm
erik.vikinger
Mitglied

Benutzerprofil
Anmeldungsdatum: 04.09.2009
Beiträge: 175
Beitrag erik.vikinger Mitglied 00:23:45 31.01.2010   Titel:              Zitieren

Hallo,

Erhard Henkes schrieb:
Es gibt leider auch viele Punkte, die man nur instinktiv richtig machen kann
Nach meiner Erfahrung sind Computer streng deterministische Gebilde, instinktive Entscheidungen sind daher nicht angebracht. ;)

Erhard Henkes schrieb:
Das bezahlt man in C++ mit viel Klassenbeziehungs-Wirrwarr und im kernel nutzlosen Overhead.
Overhead gegenüber C gibt es in C++ erst wenn man virtuelle Methoden benutzt oder die Exceptions verwendet. Insofern spricht IMHO nichts gegen die Verwendung von C++ anstelle von C, in jedem Anwendungsfall auch in einem OS-Kernel, solange man nicht zu tief in die Trickkiste von C++ greift. Auch der erzeugte Programm-Code ist dann nicht größer/langsamer als der von C.


Grüße
Erik
Erhard Henkes
Mitglied

Benutzerprofil
Anmeldungsdatum: 25.04.2000
Beiträge: 11924
Beitrag Erhard Henkes Mitglied 00:27:46 31.01.2010   Titel:              Zitieren

Das sieht dann z.B. so aus:
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
1
2
3
4
5
6
7
8
9
10
11
12
// Hilfskonstruktionen
//
// pure virtual wird dennoch ausgeführt:

extern "C"{
void __cxa_pure_virtual() {} }
//
// Ersatz für new, new[], delete und delete[] der fehlenden C++-Standard-Bibliothek

void* operator new      (size_t size) { return malloc(size); }
void* operator new[]    (size_t size) { return malloc(size); }
void  operator delete   (void* ptr)   { free(ptr); }
void  operator delete[] (void* ptr)   { free(ptr); }
//
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
// Hilfskonstruktionen
//
// pure virtual wird dennoch ausgeführt:

extern "C"{
void __cxa_pure_virtual() {} }
//
// Ersatz für new, new[], delete und delete[] der fehlenden C++-Standard-Bibliothek

void* operator new (size_t size) { return malloc(size); }
void* operator new[] (size_t size) { return malloc(size); }
void operator delete (void* ptr) { free(ptr); }
void operator delete[] (void* ptr) { free(ptr); }
//
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
// Hilfskonstruktionen
//
// pure virtual wird dennoch ausgeführt:

extern "C"{
void __cxa_pure_virtual() {} }
//
// Ersatz für new, new[], delete und delete[] der fehlenden C++-Standard-Bibliothek

void* operator new      (size_t size) { return malloc(size); }
void* operator new[]    (size_t size) { return malloc(size); }
void  operator delete   (void* ptr)   { free(ptr); }
void  operator delete[] (void* ptr)   { free(ptr); }
//

_________________
OS-Development-, C++, Win32-API-, MFC-, Chemie-, Robotik- und Flugsimulator-Tutorials
http://www.henkessoft.de/index.htm
Tobiking2
Mitglied

Benutzerprofil
Anmeldungsdatum: 12.04.2009
Beiträge: 705
Beitrag Tobiking2 Mitglied 01:51:40 31.01.2010   Titel:              Zitieren

Erhard Henkes schrieb:
Zeige mir eine konkrete Stelle in PrettyOS im Kernel, bei der uns C++ einen greifbaren Vorteil bringen würde.

Ein technischer Grund fällt mir zurzeit nicht ein, manchmal ist es aber einfach eine andere Denkweise die hilft. Bei der Floppy gibt es z.B. vom Design her Probleme, die meiner Meinung nach objektorientiert eher auffallen und leicht zu lösen sind. Erfahrene C Entwickler werden diese Meinung sicherlich nicht teilen, da sie auch so die Probleme und Lösungen direkt sehen.

Ein Problem ist das eine mögliche Erweiterung auf mehrere Floppys unbequem ist. Man müsste um eine andere Floppy anzusprechen den Wert von _CurrentDrive umsetzen. Das sorgt aber dafür das sämtliche Befehle auf der anderen Floppy ausgeführt werden. Letztendlich würde man sich also an vielen Stellen den alten Wert merken, den Wert ändern, Befehle ausführen und den Wert wieder zurücksetzen. Ist jetzt kein Beinbruch, aber unschön wenn man das mal irgendwo vergisst. In C++ wäre man wahrscheinlich als erstes auf die Idee gekommen das ganze als Klasse zu modellieren. Dann steht jedes Objekt für eine Floppy und besitzt ein separates _CurrentDrive.

Das andere Problem ist die schon öfter erwähnte Treiberschnittstelle. In C++ würde man z.B. eine Klasse BlockDevice als Schnittstelle mit Funktionen wie read und write erstellen. Klasse Floppy, Festplatte etc. erben von BlockDevice und implementieren diese Funktionen. In einer Datenstruktur wie List<BlockDevice> kann man dann alle Geräte sammeln. In C wird dies nicht ganz so ausdrucksstark dargestellt. Statt der Klasse BlockDevice hat man eine Struktur mit Funktionspointern. Die bisherige Liste in PrettyOS arbeitet bisher auch nur mit void*. Es wird also auch noch öfters gecastet werden müssen. Es ist im Prinzip die gleiche Vorgehensweise wie in C++, allerdings finde ich die C++ Variante etwas anschaulicher.
abc.w
Mitglied

Benutzerprofil
Anmeldungsdatum: 25.04.2008
Beiträge: 1364
Beitrag abc.w Mitglied 03:23:30 31.01.2010   Titel:              Zitieren

Erhard Henkes schrieb:
Das sieht dann z.B. so aus:
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
1
2
3
4
5
6
7
8
9
10
11
12
// Hilfskonstruktionen
//
// pure virtual wird dennoch ausgeführt:

extern "C"{
void __cxa_pure_virtual() {} }
//
// Ersatz für new, new[], delete und delete[] der fehlenden C++-Standard-Bibliothek

void* operator new      (size_t size) { return malloc(size); }
void* operator new[]    (size_t size) { return malloc(size); }
void  operator delete   (void* ptr)   { free(ptr); }
void  operator delete[] (void* ptr)   { free(ptr); }
//
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
// Hilfskonstruktionen
//
// pure virtual wird dennoch ausgeführt:

extern "C"{
void __cxa_pure_virtual() {} }
//
// Ersatz für new, new[], delete und delete[] der fehlenden C++-Standard-Bibliothek

void* operator new (size_t size) { return malloc(size); }
void* operator new[] (size_t size) { return malloc(size); }
void operator delete (void* ptr) { free(ptr); }
void operator delete[] (void* ptr) { free(ptr); }
//
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
// Hilfskonstruktionen
//
// pure virtual wird dennoch ausgeführt:

extern "C"{
void __cxa_pure_virtual() {} }
//
// Ersatz für new, new[], delete und delete[] der fehlenden C++-Standard-Bibliothek

void* operator new      (size_t size) { return malloc(size); }
void* operator new[]    (size_t size) { return malloc(size); }
void  operator delete   (void* ptr)   { free(ptr); }
void  operator delete[] (void* ptr)   { free(ptr); }
//


Oder so (das ist jetzt natürlich kein Musterbeispiel, falls jemand trotzdem Kritik hat, gerne her damit):

C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#include "datatypes.h"

#ifdef
MAX_MEMORY_BLOCKS
#error
Already defined.
#else

/// Specifies number of memory blocks used for dynamic memory
#define
MAX_MEMORY_BLOCKS   (32u)
#endif

#ifdef
MAX_BLOCK_SIZE
#error
Already defined.
#else

/// Specifies number of uint32_t words contained in one memory block
#define
MAX_BLOCK_SIZE      (1023u)
#endif


/// Structure for memory block
static struct tMemoryBlock
{
    uint32_t used;                      ///< Flag, indicating if memory block is used or not
    uint32_t data[MAX_BLOCK_SIZE];      ///< Data words of the memory block
}
MemoryBlock[MAX_MEMORY_BLOCKS];

/// Check size of one MemoryBlock structure. It is expected to be a fixed number of bytes.
typedef char CheckSize_tMemoryBlock[sizeof(MemoryBlock[0]) == 4096 ? 1: -1];

void* operator new(uint32_t size)
{
    uint32_t i = 0u;
    uint32_t found_i = 0u;

    size = size;

    // This loop goes through all memory blocks and looks for free one
    for (i = 0u; i < MAX_MEMORY_BLOCKS; ++i)
    {
        if (0u == MemoryBlock[i].used)
        {
            // Found one unused memory block
            // Set found index and break the loop

            found_i = i;
            i = (MAX_MEMORY_BLOCKS - 1u);
        }
    }

    // Set used flag
    ++(MemoryBlock[found_i].used);

    return &(MemoryBlock[found_i].data[0]);
}

void operator delete(void* pData)
{
    uint32_t i = 0u;

    // This loop goes through all memory blocks and checks, if
    // the pointer points to it. The corresponding memory block
    // gets unused then.

    for (i = 0u; i < MAX_MEMORY_BLOCKS; ++i)
    {
        const void* pBegin = &(MemoryBlock[i].data[0]);
        const void* pEnd = &(MemoryBlock[i].data[MAX_BLOCK_SIZE - 1u]);

        if ((pData >= pBegin) && (pData <= pEnd))
        {
            // Found one used block, no sense to continue the loop
            // Set it as unused and break the loop

            MemoryBlock[i].used = 0;
            i = (MAX_MEMORY_BLOCKS - 1u);
        }
    }
}

void* operator new(uint32_t size, void* pBuffer)
{
    size = size;
    // Because this function is "placement new", just return the
    // pointer to the buffer

    return pBuffer;
}

void* operator new[](uint32_t size)
{
    return operator new(size);
}

void operator delete[](void* pData)
{
    operator delete(pData);
}
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#include "datatypes.h"

#ifdef
MAX_MEMORY_BLOCKS
#error
Already defined.
#else

/// Specifies number of memory blocks used for dynamic memory
#define
MAX_MEMORY_BLOCKS (32u)
#endif

#ifdef
MAX_BLOCK_SIZE
#error
Already defined.
#else

/// Specifies number of uint32_t words contained in one memory block
#define
MAX_BLOCK_SIZE (1023u)
#endif


/// Structure for memory block
static struct tMemoryBlock
{
uint32_t used; ///< Flag, indicating if memory block is used or not
uint32_t data[MAX_BLOCK_SIZE]; ///< Data words of the memory block
}
MemoryBlock[MAX_MEMORY_BLOCKS];

/// Check size of one MemoryBlock structure. It is expected to be a fixed number of bytes.
typedef char CheckSize_tMemoryBlock[sizeof(MemoryBlock[0]) == 4096 ? 1: -1];

void* operator new(uint32_t size)
{
uint32_t i = 0u;
uint32_t found_i = 0u;

size = size;

// This loop goes through all memory blocks and looks for free one
for (i = 0u; i < MAX_MEMORY_BLOCKS; ++i)
{
if (0u == MemoryBlock[i].used)
{
// Found one unused memory block
// Set found index and break the loop

found_i = i;
i = (MAX_MEMORY_BLOCKS - 1u);
}
}

// Set used flag
++(MemoryBlock[found_i].used);

return &(MemoryBlock[found_i].data[0]);
}

void operator delete(void* pData)
{
uint32_t i = 0u;

// This loop goes through all memory blocks and checks, if
// the pointer points to it. The corresponding memory block
// gets unused then.

for (i = 0u; i < MAX_MEMORY_BLOCKS; ++i)
{
const void* pBegin = &(MemoryBlock[i].data[0]);
const void* pEnd = &(MemoryBlock[i].data[MAX_BLOCK_SIZE - 1u]);

if ((pData >= pBegin) && (pData <= pEnd))
{
// Found one used block, no sense to continue the loop
// Set it as unused and break the loop

MemoryBlock[i].used = 0;
i = (MAX_MEMORY_BLOCKS - 1u);
}
}
}

void* operator new(uint32_t size, void* pBuffer)
{
size = size;
// Because this function is "placement new", just return the
// pointer to the buffer

return pBuffer;
}

void* operator new[](uint32_t size)
{
return operator new(size);
}

void operator delete[](void* pData)
{
operator delete(pData);
}
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#include "datatypes.h"

#ifdef
MAX_MEMORY_BLOCKS
#error
Already defined.
#else

/// Specifies number of memory blocks used for dynamic memory
#define
MAX_MEMORY_BLOCKS   (32u)
#endif

#ifdef
MAX_BLOCK_SIZE
#error
Already defined.
#else

/// Specifies number of uint32_t words contained in one memory block
#define
MAX_BLOCK_SIZE      (1023u)
#endif


/// Structure for memory block
static struct tMemoryBlock
{
    uint32_t used;                      ///< Flag, indicating if memory block is used or not
    uint32_t data[MAX_BLOCK_SIZE];      ///< Data words of the memory block
}
MemoryBlock[MAX_MEMORY_BLOCKS];

/// Check size of one MemoryBlock structure. It is expected to be a fixed number of bytes.
typedef char CheckSize_tMemoryBlock[sizeof(MemoryBlock[0]) == 4096 ? 1: -1];

void* operator new(uint32_t size)
{
    uint32_t i = 0u;
    uint32_t found_i = 0u;

    size = size;

    // This loop goes through all memory blocks and looks for free one
    for (i = 0u; i < MAX_MEMORY_BLOCKS; ++i)
    {
        if (0u == MemoryBlock[i].used)
        {
            // Found one unused memory block
            // Set found index and break the loop

            found_i = i;
            i = (MAX_MEMORY_BLOCKS - 1u);
        }
    }

    // Set used flag
    ++(MemoryBlock[found_i].used);

    return &(MemoryBlock[found_i].data[0]);
}

void operator delete(void* pData)
{
    uint32_t i = 0u;

    // This loop goes through all memory blocks and checks, if
    // the pointer points to it. The corresponding memory block
    // gets unused then.

    for (i = 0u; i < MAX_MEMORY_BLOCKS; ++i)
    {
        const void* pBegin = &(MemoryBlock[i].data[0]);
        const void* pEnd = &(MemoryBlock[i].data[MAX_BLOCK_SIZE - 1u]);

        if ((pData >= pBegin) && (pData <= pEnd))
        {
            // Found one used block, no sense to continue the loop
            // Set it as unused and break the loop

            MemoryBlock[i].used = 0;
            i = (MAX_MEMORY_BLOCKS - 1u);
        }
    }
}

void* operator new(uint32_t size, void* pBuffer)
{
    size = size;
    // Because this function is "placement new", just return the
    // pointer to the buffer

    return pBuffer;
}

void* operator new[](uint32_t size)
{
    return operator new(size);
}

void operator delete[](void* pData)
{
    operator delete(pData);
}
abc.w
Mitglied

Benutzerprofil
Anmeldungsdatum: 25.04.2008
Beiträge: 1364
Beitrag abc.w Mitglied 00:26:47 07.02.2010   Titel:              Zitieren

Tobiking2 schrieb:
In C++ würde man z.B. eine Klasse BlockDevice als Schnittstelle mit Funktionen wie read und write erstellen. Klasse Floppy, Festplatte etc. erben von BlockDevice und implementieren diese Funktionen. In einer Datenstruktur wie List<BlockDevice> kann man dann alle Geräte sammeln. In C wird dies nicht ganz so ausdrucksstark dargestellt. Statt der Klasse BlockDevice hat man eine Struktur mit Funktionspointern. Die bisherige Liste in PrettyOS arbeitet bisher auch nur mit void*. Es wird also auch noch öfters gecastet werden müssen. Es ist im Prinzip die gleiche Vorgehensweise wie in C++, allerdings finde ich die C++ Variante etwas anschaulicher.

Lese gerade zufällig in c't (Heft 19, 31.8.2009):
Zitat:
Kritische Lücke im Linux-Kernel
Eine Sicherheitslücke im Linux-Kernel betrifft alle Versionen ... seit Mai 2001. ... Üblicherweise deklariert eine Pointer-Struktur, welche Operationen ein Socket untersützt, etwa accept, bind und so weiter. Ist aber die Operation accept nicht implementiert, so sollte sie auf eine vordefinierte Komponente wie sock_no_accept zeigen. Dies ist offensichtlich nicht bei allen implementierten Protokollen der Fall...

So ist es, man hat ja keine Überwachung durch den Compiler, also muss der Programmierer selbst darauf achten, dass er alle Funktions-Pointer setzt bzw. auf deren Gültigkeit prüft...
Erhard Henkes
Mitglied

Benutzerprofil
Anmeldungsdatum: 25.04.2000
Beiträge: 11924
Beitrag Erhard Henkes Mitglied 01:15:39 07.02.2010   Titel:              Zitieren

Die Stärken moderner Programmiersprachen bestehen in der Fehlervermeidung und -überwachung. Allerdings hat man dafür bei C einen einfacheren Umgang mit der Materie. C++ fordert dem Entwickler hier deutlich mehr ab.

Warum nicht gleich Java für OSDEV?

_________________
OS-Development-, C++, Win32-API-, MFC-, Chemie-, Robotik- und Flugsimulator-Tutorials
http://www.henkessoft.de/index.htm
volkard
Moderator

Benutzerprofil
Anmeldungsdatum: 06.04.2000
Beiträge: 24349
Beitrag volkard Moderator 03:28:22 07.02.2010   Titel:              Zitieren

Erhard Henkes schrieb:
Warum nicht gleich Java für OSDEV?

Unter anderem weil Java sich wieder von der Politik des Fehlervermeidens verabschiedet, dabei wieder unter das Niveau von C fällt (,wobei ich mit "Vermeiden" nicht meine, daß man sie nur auffängt), und langsamer ist und man nur über Umwege an die Hardware kommt, was für ein BS, wie ich füchte, dann doch zu nervig wird.

_________________
http://www.venganza.info/
plonk fürs Forum v1.02
Tobiking2
Mitglied

Benutzerprofil
Anmeldungsdatum: 12.04.2009
Beiträge: 705
Beitrag Tobiking2 Mitglied 04:40:07 07.02.2010   Titel:              Zitieren

Erhard Henkes schrieb:
Allerdings hat man dafür bei C einen einfacheren Umgang mit der Materie. C++ fordert dem Entwickler hier deutlich mehr ab.

Was meinst du denn konkret damit? Der meiste Code von PrettyOS ist ebenfalls valider C++ Code. An vielen Stellen fehlt nur ein expliziter Cast oder ein extern "C" wenn die Funktionen von Assembler aus aufgerufen werden. Das ist weder schwieriger noch weiter von der Materie entfernt.

Im Gegenzug erhoffe ich mir das du nicht mehr so etwas wie an konkrete Laufwerke gekoppelte Dateisyetemfunktionen schreibst. Ich habe dir ja schon prophezeit, dass die Fehlersuche die du jetzt für das Fat Dateisystem auf Diskette durchführst, in ähnlicher Form wieder auftritt wenn du beides voneinander trennst oder die Fat Funktionen auf andere Laufwerke überträgst. Es wäre deutlich einfacher wenn man es also gleich richtig macht. Komplizierter ist das ganze sicherlich nicht.
rüdiger
Moderator

Benutzerprofil
Anmeldungsdatum: 11.07.2001
Beiträge: 22819
Beitrag rüdiger Moderator 12:25:40 07.02.2010   Titel:              Zitieren

C++ hat nach meiner Ansicht den Vorteil, dass man mehr Semantik im Code unterbringen kann. Und mit Templates wird das verwenden von Datenstrukturen stark vereinfacht.

Im Kernel würde ich aber natürlich auf den Runtime-abhängigen Teil verzichten (also Exceptions, RTTI).

@abc.w
size_t anstelle uint32_t!

Aber der Code wirkt teilweise ein bisschen komisch
C/C++ Code:
size = size;
C/C++ Code:
size = size;
C/C++ Code:
size = size;


oder anstelle von break dieses Konstrukt
C/C++ Code:
for (i = 0u; i < MAX_MEMORY_BLOCKS; ++i)
{
//...
      i = (MAX_MEMORY_BLOCKS - 1u);
}
C/C++ Code:
for (i = 0u; i < MAX_MEMORY_BLOCKS; ++i)
{
//...
i = (MAX_MEMORY_BLOCKS - 1u);
}
C/C++ Code:
for (i = 0u; i < MAX_MEMORY_BLOCKS; ++i)
{
//...
      i = (MAX_MEMORY_BLOCKS - 1u);
}


Grobe Fehler:
size wird ignoriert: wenn man mehr als MAX_BLOCK_SIZE Speicher anfordert, dann bekommt man einen Pointer auf einen zu kleinen Speicherbereich.

Und wenn man mehr als MAX_MEMORY_BLOCKS anfordert, dann überschreibt man immer wieder den ersten Block.

_________________
.
abc.w
Mitglied

Benutzerprofil
Anmeldungsdatum: 25.04.2008
Beiträge: 1364
Beitrag abc.w Mitglied 13:18:51 07.02.2010   Titel:              Zitieren

rüdiger schrieb:
@abc.w
size_t anstelle uint32_t!

Ja... Hm, habe nur uint32_t und uint8_t als Datentypen.

rüdiger schrieb:
Aber der Code wirkt teilweise ein bisschen komisch... ...Grobe Fehler...

Ja, zu viel von KISS (keep it sehr stupid)... :) Ist sowieso nur zum Testen und Hauptsache, kein malloc(). Funktionierenden Kernel in C++ habe ich auch nicht und bin sehr weit davon entfernt, aber es hat seinen Reiz...
Badestrand
Mitglied

Benutzerprofil
Anmeldungsdatum: 29.08.2006
Beiträge: 4342
Beitrag Badestrand Mitglied 19:07:16 21.02.2010   Titel:              Zitieren

Erhard Henkes schrieb:
Zeige mir eine konkrete Stelle in PrettyOS im Kernel, bei der uns C++ einen greifbaren Vorteil bringen würde.

Im Moment könnte ich es ganz gut für das Kontrollieren des Interrupt-Flags gebrauchen (sti/cli):
Wenn ich eine Routine schützen will, sieht das ja so aus:
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
1
2
3
4
5
6
7
8
9
10
11
12
void foo()
{
    cli();

    if ( x )
    {
        sti();
        return;
    }

    sti();
}
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
void foo()
{
cli();

if ( x )
{
sti();
return;
}

sti();
}
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
void foo()
{
    cli();

    if ( x )
    {
        sti();
        return;
    }

    sti();
}


Das ist ja noch halbwegs OK. Das Problem dabei ist nur, dass foo u.U. eigentlich gar nicht die Interrupts anschalten darf. Z.B. wenn foo aus einer ebenfalls geschützten Funktion aufgerufen wird:
C/C++ Code:
1
2
3
4
5
6
7
8
1
2
3
4
5
6
7
8
void bar()
{
    cli();
    foo();
    // Hier sind Interrupts leider wieder eingeschaltet
    doImportantStuff();
    sti();
}
C/C++ Code:
1
2
3
4
5
6
7
8
void bar()
{
cli();
foo();
// Hier sind Interrupts leider wieder eingeschaltet
doImportantStuff();
sti();
}
C/C++ Code:
1
2
3
4
5
6
7
8
void bar()
{
    cli();
    foo();
    // Hier sind Interrupts leider wieder eingeschaltet
    doImportantStuff();
    sti();
}


D.h. wir brauchen eigentlich auch noch Abfrage, ob Interrupts beim cli-Aufruf gesetzt waren:
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void foo()
{
    // cli sollte zurückgeben, ob Interrupts vorher gesetzt waren.
    bool interrupts_enabled = cli();

    if ( x )
    {
        if ( interrupts_enabled )
            sti();
        return;
    }

    if ( interrupts_enabled )
        sti();
}
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void foo()
{
// cli sollte zurückgeben, ob Interrupts vorher gesetzt waren.
bool interrupts_enabled = cli();

if ( x )
{
if ( interrupts_enabled )
sti();
return;
}

if ( interrupts_enabled )
sti();
}
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void foo()
{
    // cli sollte zurückgeben, ob Interrupts vorher gesetzt waren.
    bool interrupts_enabled = cli();

    if ( x )
    {
        if ( interrupts_enabled )
            sti();
        return;
    }

    if ( interrupts_enabled )
        sti();
}


Das an jeden Ausgang zu setzen, ist irgendwie eklig. Mit C++ wäre das doch eher einfacher:
C/C++ Code:
void foo()
{
    DisableInterrupts interrupt_protection;
    // ...
}
C/C++ Code:
void foo()
{
DisableInterrupts interrupt_protection;
// ...
}
C/C++ Code:
void foo()
{
    DisableInterrupts interrupt_protection;
    // ...
}
abc.w
Mitglied

Benutzerprofil
Anmeldungsdatum: 25.04.2008
Beiträge: 1364
Beitrag abc.w Mitglied 19:26:53 21.02.2010   Titel:              Zitieren

Man müsste ja noch bei jedem return aufpassen, die Interrupts wieder einzuschalten, was man in einem Destruktor machen könnte :o)
Badestrand
Mitglied

Benutzerprofil
Anmeldungsdatum: 29.08.2006
Beiträge: 4342
Beitrag Badestrand Mitglied 19:35:03 21.02.2010   Titel:              Zitieren

abc.w schrieb:
Man müsste ja noch bei jedem return aufpassen, die Interrupts wieder einzuschalten, was man in einem Destruktor machen könnte :o)

Darauf wollte ich eigentlich hinaus :p "DisableInterrupts" als Ersatz für das Ausschalten der Interrupts, merken ob sie an waren und gegebenenfalls wieder Anschalten der Interrupts beim rausspringen. Und das mit einem Einzeiler.
Erhard Henkes
Mitglied

Benutzerprofil
Anmeldungsdatum: 25.04.2000
Beiträge: 11924
Beitrag Erhard Henkes Mitglied 03:04:00 22.08.2010   Titel:              Zitieren

Das Thema C vs C++ ist nicht neu:
http://forum.osdev.org/viewtopic.php?f=15&t=22406&start=0

Die Diskussion ist sehr unstrukturiert, aber einige Erfahrungsbeiträge sind lesenswert. In Summe gesehen gehen beide Sprachen, wenn man es richtig anpackt.

Ich persönlich bin überrascht, wie gut man in C einen Kernel programmieren kann.
Daher sehe ich keinen wirklichen Vorteil in C++.

_________________
OS-Development-, C++, Win32-API-, MFC-, Chemie-, Robotik- und Flugsimulator-Tutorials
http://www.henkessoft.de/index.htm


Zuletzt bearbeitet von Erhard Henkes am 03:21:15 22.08.2010, insgesamt 1-mal bearbeitet
Mr X
Mitglied

Benutzerprofil
Anmeldungsdatum: 18.09.2007
Beiträge: 1073
Beitrag Mr X Mitglied 09:42:20 22.08.2010   Titel:              Zitieren

Zitat:
Daher sehe ich keinen wirklichen Vorteil in C++.

Ich sehe durchaus Vorteile. Funktionsüberladung ist immer gut^^, Dinge wie Listen ließen sich viel leichter nutzen (Konstruktoren/Destruktoren, u.a.), statt void* data mitzuführen könnte man einfach von einer Basisklasse Erben.
Artchi
Autor

Benutzerprofil
Anmeldungsdatum: 16.03.2002
Beiträge: 8576
Beitrag Artchi Autor 12:41:38 22.08.2010   Titel:              Zitieren

Das wichtigste: Information Hiding! Sprich Kapselung von Daten, so das man einen kontrollierten Zugriff erlauben kann. Völlig unabhängig von Vtable, Template-Bloat u.a. Mythen die Performanceverlust bedeuten sollen.

Gerade die Kapselung kann viel zur Qualität eines Projektes (egal ob Kernel oder Anwendungen) beitragen. Sowohl weniger Fehler zur Laufzeit, als auch einer einfachen Wartung.

_________________
Bring back the Windows Start Menu Petition | GoPetition


Zuletzt bearbeitet von Artchi am 12:42:16 22.08.2010, insgesamt 1-mal bearbeitet
Erhard Henkes
Mitglied

Benutzerprofil
Anmeldungsdatum: 25.04.2000
Beiträge: 11924
Beitrag Erhard Henkes Mitglied 14:32:37 22.08.2010   Titel:              Zitieren

Kapselung ( engl.: information hiding oder encapsulation ) ist in der Tat der wesentliche Effekt der Objektorientierung. Das ist ein klarer Pluspunkt für C++.
http://www.henkessoft.de/C++/C++/kapselung.htm

_________________
OS-Development-, C++, Win32-API-, MFC-, Chemie-, Robotik- und Flugsimulator-Tutorials
http://www.henkessoft.de/index.htm
Zeus
Mitglied

Benutzerprofil
Anmeldungsdatum: 25.09.2003
Beiträge: 2582
Beitrag Zeus Mitglied 14:45:42 22.08.2010   Titel:              Zitieren

Information Hiding kann man in C auch betreiben, aber Encapsulation nicht. Zwei Begriffe die nicht äquivalent sind.

_________________
http://sourceforge.net/projects/nano-lang/
abc.w
Mitglied

Benutzerprofil
Anmeldungsdatum: 25.04.2008
Beiträge: 1364
Beitrag abc.w Mitglied 17:36:30 22.08.2010   Titel:              Zitieren

Erhard Henkes schrieb:
.. Ich persönlich bin überrascht, wie gut man in C einen Kernel programmieren kann. ...

Liegt es vielleicht daran, dass die Tools gcc und binutils verwendet werden? ;)
Erhard Henkes
Mitglied

Benutzerprofil
Anmeldungsdatum: 25.04.2000
Beiträge: 11924
Beitrag Erhard Henkes Mitglied 17:47:16 22.08.2010   Titel:              Zitieren

Dass man auch in C++ interessante OS bauen kann, wird hier von James Molloy und Jörg Pfähler ("bluecode") gezeigt:
http://www.lowlevel.eu/wiki/Pedigree

_________________
OS-Development-, C++, Win32-API-, MFC-, Chemie-, Robotik- und Flugsimulator-Tutorials
http://www.henkessoft.de/index.htm
dot
Mitglied

Benutzerprofil
Anmeldungsdatum: 20.05.2004
Beiträge: 3839
Beitrag dot Mitglied 17:48:37 22.08.2010   Titel:              Zitieren

Imo gibt es nur einen einzigen Grund heutzutage noch C zu benutzen: Wenn es für eine Zielplattform keinen C++ Compiler gibt. Alleine schon wegen templates, overloading und RAII würde ich mich jederzeit für C++ entscheiden wenn ich die Wahl hätte. Dass C++ einen inhärenten Performancenachteil gegenüber C hätte ist ein Märchen, man kann genausogut Beispiele aufzeigen wo das Gegenteil der Fall ist (z.B. das allseits beliebte std::sort vs qsort()). Natürlich hat C++ einige Sprachfeatures die einen gewissen Overhead mit sich bringen. Allerdings darf man dabei nicht vergessen dass, wenn man ähnliche Systeme direkt in C implementieren würde, am Ende C Code rauskommt der mehr oder weniger genau das tut was der C++ Compiler einem abnehmen würde und daher auch vergleichbaren Overhead mit sich bringt (Beispiel die gern verteufelten virtuelle Funktionen: In C greift man dafür eben in irgendeiner Form auf Function Pointer zurück und hat am Ende den selben Overhead).

_________________
one point of view will never reveal the entire scene.


Zuletzt bearbeitet von dot am 18:06:14 22.08.2010, insgesamt 6-mal bearbeitet
Erhard Henkes
Mitglied

Benutzerprofil
Anmeldungsdatum: 25.04.2000
Beiträge: 11924
Beitrag Erhard Henkes Mitglied 17:55:35 22.08.2010   Titel:              Zitieren

Zitat:
Information Hiding kann man in C auch betreiben
Kannst du dies bitte an Beispielen darstellen?

_________________
OS-Development-, C++, Win32-API-, MFC-, Chemie-, Robotik- und Flugsimulator-Tutorials
http://www.henkessoft.de/index.htm
taljeth
Mitglied

Benutzerprofil
Anmeldungsdatum: 11.09.2009
Beiträge: 148
Beitrag taljeth Mitglied 09:58:54 23.08.2010   Titel:              Zitieren

foo.h:
C/C++ Code:
struct foo;

struct foo* create_foo(void);
void do_it(struct foo* xyz);
C/C++ Code:
struct foo;

struct foo* create_foo(void);
void do_it(struct foo* xyz);
C/C++ Code:
struct foo;

struct foo* create_foo(void);
void do_it(struct foo* xyz);


foo.c:
C/C++ Code:
1
2
3
4
5
6
7
8
9
1
2
3
4
5
6
7
8
9
#include "foo.h"

struct foo {
    int bar;
    char baz[42];
};

struct foo* create_foo(void) { return calloc(1, sizeof(struct foo)); }
void do_it(struct foo* xyz) { ... }
C/C++ Code:
1
2
3
4
5
6
7
8
9
#include "foo.h"

struct foo {
int bar;
char baz[42];
};

struct foo* create_foo(void) { return calloc(1, sizeof(struct foo)); }
void do_it(struct foo* xyz) { ... }
C/C++ Code:
1
2
3
4
5
6
7
8
9
#include "foo.h"

struct foo {
    int bar;
    char baz[42];
};

struct foo* create_foo(void) { return calloc(1, sizeof(struct foo)); }
void do_it(struct foo* xyz) { ... }


Von außen sieht niemand, wie eine struct foo tatsächlich aussieht, man hantiert nur mit Pointern darauf.

_________________
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.
Lowlevel - die deutschsprachige OS-Dev-Community
Artchi
Autor

Benutzerprofil
Anmeldungsdatum: 16.03.2002
Beiträge: 8576
Beitrag Artchi Autor 10:19:34 23.08.2010   Titel:              Zitieren

Stellen wir fest:
1. Es ist sehr nützlich Kapselung/Information-Hiding (ich meine nicht Implementation-Hiding ähnlich Pimpl) zu betreiben.
2. Es ist mit C-Mitteln in gewisser Weise möglich.

Meine Frage: ist es in der C-Welt Usus, es so zu machen? Falls nicht, bitte ich um eine Erklärung, warum es nicht Usus ist. :D

_________________
Bring back the Windows Start Menu Petition | GoPetition


Zuletzt bearbeitet von Artchi am 10:19:54 23.08.2010, insgesamt 1-mal bearbeitet
Zeus
Mitglied

Benutzerprofil
Anmeldungsdatum: 25.09.2003
Beiträge: 2582
Beitrag Zeus Mitglied 13:11:57 23.08.2010   Titel:              Zitieren

@taljeth
Danke, genau sowas hatte ich Sinn.

Man sieht aber auch es gibt Probleme, wenn man die Idee von vorher aufgreift, Polymorphie durch Funktionszeiger zu emulieren.

_________________
http://sourceforge.net/projects/nano-lang/
dot
Mitglied

Benutzerprofil
Anmeldungsdatum: 20.05.2004
Beiträge: 3839
Beitrag dot Mitglied 17:43:20 23.08.2010   Titel:              Zitieren

Artchi schrieb:
Meine Frage: ist es in der C-Welt Usus, es so zu machen? Falls nicht, bitte ich um eine Erklärung, warum es nicht Usus ist. :D

Afaik is das was taljeth beschrieben hat in C eine relativ gängige Sache.

_________________
one point of view will never reveal the entire scene.
Erhard Henkes
Mitglied

Benutzerprofil
Anmeldungsdatum: 25.04.2000
Beiträge: 11924
Beitrag Erhard Henkes Mitglied 14:28:07 29.08.2010   Titel:              Zitieren

http://d3s.mff.cuni.cz/publications/Decky-FormallyVerifiedOS.pdf
Chapter 2.2 The C Programming Language:
Zitat:
A large majority of OSes is coded in the C programming language (HelenOS is no exception to this). The choice of C in the case of kernel is usually wellmotivated, since the C language was designed specifically for implementing system software [10]: It is reasonably low-level in the sense that it allows to access the memory and other hardware resources with similar effectiveness as from assembler; It also requires almost no run-time support and it exports many features of the von Neumann hardware architecture to the programmer in a very straightforward, but still relatively portable way.

However, what is the biggest advantage of C in terms of run-time performance is also the biggest weakness for formal reasoning. The permissive memory access model of C, the lack of any reference safety enforcement, the weak type system and generally little semantic information in the code – all these properties do not allow to make many general assumptions about the code.

_________________
OS-Development-, C++, Win32-API-, MFC-, Chemie-, Robotik- und Flugsimulator-Tutorials
http://www.henkessoft.de/index.htm


Zuletzt bearbeitet von Erhard Henkes am 14:29:15 29.08.2010, insgesamt 2-mal bearbeitet
abc.w
Mitglied

Benutzerprofil
Anmeldungsdatum: 25.04.2008
Beiträge: 1364
Beitrag abc.w Mitglied 18:20:34 29.08.2010   Titel:              Zitieren

Zitat:
... However, what is the biggest advantage of C in terms of run-time performance is also the biggest weakness for formal reasoning. The permissive memory access model of C, the lack of any reference safety enforcement, the weak type system and generally little semantic information in the code – all these properties do not allow to make many general assumptions about the code.

Viele Denkfallen und Fehler im C Quellcode lassen sich mit Hilfe der statischen Code-Analyse Tools wie splint aufdecken und vermeiden (es gibt auch entsprechende Tools für C++, kenne leider keine kostenlosen...).
Das andere Problem und meiner Meinung nach, das schwergewichtigere, ist:
Zitat:
In C, almost everything is left to the programmer who is free to set the rules.
Erhard Henkes
Mitglied

Benutzerprofil
Anmeldungsdatum: 25.04.2000
Beiträge: 11924
Beitrag Erhard Henkes Mitglied 19:01:09 29.08.2010   Titel:              Zitieren

Zitat:
... almost everything is left to the programmer who is free to set the rules.

Entwickler eines eigenen OS schätzen diese Freiheiten und sollten damit auch umgehen können. :)

_________________
OS-Development-, C++, Win32-API-, MFC-, Chemie-, Robotik- und Flugsimulator-Tutorials
http://www.henkessoft.de/index.htm
dot
Mitglied

Benutzerprofil
Anmeldungsdatum: 20.05.2004
Beiträge: 3839
Beitrag dot Mitglied 19:02:30 29.08.2010   Titel:              Zitieren

C++ schränkt diese Freiheiten in keiner Form ein...

_________________
one point of view will never reveal the entire scene.
Mr X
Mitglied

Benutzerprofil
Anmeldungsdatum: 18.09.2007
Beiträge: 1073
Beitrag Mr X Mitglied 19:17:42 29.08.2010   Titel:              Zitieren

abc.w schrieb:
Zitat:
... However, what is the biggest advantage of C in terms of run-time performance is also the biggest weakness for formal reasoning. The permissive memory access model of C, the lack of any reference safety enforcement, the weak type system and generally little semantic information in the code – all these properties do not allow to make many general assumptions about the code.

Viele Denkfallen und Fehler im C Quellcode lassen sich mit Hilfe der statischen Code-Analyse Tools wie splint aufdecken und vermeiden (es gibt auch entsprechende Tools für C++, kenne leider keine kostenlosen...).
Das andere Problem und meiner Meinung nach, das schwergewichtigere, ist:
Zitat:
In C, almost everything is left to the programmer who is free to set the rules.

Splint... Ich habs tatsächlich versucht, es hat _nur_ Müll ausgegeben, keinen sinnvollen Hinweis unter ca. 5000 Hinweisen.

Cppcheck find ich persönlich besser, kann mit C und C++ umgehen.


Zuletzt bearbeitet von Mr X am 19:22:21 29.08.2010, insgesamt 1-mal bearbeitet
abc.w
Mitglied

Benutzerprofil
Anmeldungsdatum: 25.04.2008
Beiträge: 1364
Beitrag abc.w Mitglied 20:14:18 29.08.2010   Titel:              Zitieren

Mr X schrieb:
Splint... Ich habs tatsächlich versucht, es hat _nur_ Müll ausgegeben, keinen sinnvollen Hinweis unter ca. 5000 Hinweisen.

Ja, ich weiss, dass man Tausende Warnungen bekommt, aber ich habe die Erfahrung gemacht, dass jede Warnung einen Bug bedeuten kann... d.h. in den 5000 Warnungen würde ich jetzt 5000 potentielle Bugs sehen...

Mr X schrieb:
Cppcheck find ich persönlich besser, kann mit C und C++ umgehen.

Danke für den Tipp!
Erhard Henkes
Mitglied

Benutzerprofil
Anmeldungsdatum: 25.04.2000
Beiträge: 11924
Beitrag Erhard Henkes Mitglied 21:56:23 29.08.2010   Titel:              Zitieren

MrX ist einer der führenden Developer von PrettyOS. Wenn er sagt, dass die Resultate wenig hilfreich sind, dann ist dem so.

_________________
OS-Development-, C++, Win32-API-, MFC-, Chemie-, Robotik- und Flugsimulator-Tutorials
http://www.henkessoft.de/index.htm
Mr X
Mitglied

Benutzerprofil
Anmeldungsdatum: 18.09.2007
Beiträge: 1073
Beitrag Mr X Mitglied 22:25:38 29.08.2010   Titel:              Zitieren

Die Behauptung ist gewagt, ehenkes.

Zitat:
Ja, ich weiss, dass man Tausende Warnungen bekommt, aber ich habe die Erfahrung gemacht, dass jede Warnung einen Bug bedeuten kann... d.h. in den 5000 Warnungen würde ich jetzt 5000 potentielle Bugs sehen...

Ein Teil der Meldungen kam daher, das es nicht mit C99 oder GCC-spezifischen Dingen klarkam (leider brach er daraufhin jedes Mal ab - ich musste jede Datei separat checken). Ein Problem, das cppcheck übrigens nicht hat. Dann waren die meisten Fehlermeldungen so formuliert, das man nicht verstand, was es von einem will. Oft beklagte er sich auch nur, weil man selbst einige Dinge definiert, die ein Anwendungsprogramm einfach aus der Standardlib beziehen würde (malloc, free, size_t, ...). Richtig war allerdings, das man keine Namen mit _ am Anfang verwenden sollte, da das für den Compiler "reserviert" ist.
abc.w
Mitglied

Benutzerprofil
Anmeldungsdatum: 25.04.2008
Beiträge: 1364
Beitrag abc.w Mitglied 21:20:41 02.09.2010   Titel:              Zitieren

Ich habe mal splint über euren Quellcode laufen lassen, weiss jetzt nicht, welche Version, aufgerufen mit diesen Parametern:
Code:
splint -I /tmp/prettyos/trunk/Source/user/user_tools -I /tmp/prettyos/trunk/Source/kernel -booltype bool +nolib +gnuextensions +trytorecover blabla.c
Code:
splint -I /tmp/prettyos/trunk/Source/user/user_tools -I /tmp/prettyos/trunk/Source/kernel -booltype bool +nolib +gnuextensions +trytorecover blabla.c
Code:
splint -I /tmp/prettyos/trunk/Source/user/user_tools -I /tmp/prettyos/trunk/Source/kernel -booltype bool +nolib +gnuextensions +trytorecover blabla.c

und da sagt splint mehrmals "A memory leak has been detected" u. ä. oder Rückgabewerte von Funktionen unbenutzt, oder unsigned mit signed gemischt, oder untereinander nicht kompatible Datentypen gemischt u. ä. Hört sich alles nicht so gut an :)
Erhard Henkes
Mitglied

Benutzerprofil
Anmeldungsdatum: 25.04.2000
Beiträge: 11924
Beitrag Erhard Henkes Mitglied 22:19:07 02.09.2010   Titel:              Zitieren

Zitat:
"A memory leak has been detected"
<--- das ist interessant. Wir kontrollieren ja bereits mit dem heap logger und überwachen auch den physischen Speicher auf leaks. Da ist mir momentan nix aufgefallen.

_________________
OS-Development-, C++, Win32-API-, MFC-, Chemie-, Robotik- und Flugsimulator-Tutorials
http://www.henkessoft.de/index.htm
Mr X
Mitglied

Benutzerprofil
Anmeldungsdatum: 18.09.2007
Beiträge: 1073
Beitrag Mr X Mitglied 23:14:57 02.09.2010   Titel:              Zitieren

ehenkes: Sämtliche Log-Funktionen zeigen nur dann was, wenn das Leak tatsächlich eintritt, und das ist oft nur in seltenen Fällen der Fall.

abc.w:
Zitat:
Rückgabewerte von Funktionen unbenutzt

Halte ich für gängigen Stil und korrekt. (Nagut, wenns malloc wäre natürlich nicht ;) )

Das memory-leak ist da interessanter. Leider funktioniert Splint auch mit den diversen Parametern von dir und einem Update auf 3.1.2 (Vorher gabs für Windows nur uralt-Versionen) nicht, auch wenn sich die Lage durchaus gebessert hat. Er krepiert jetzt in ckernel.c Zeile 126, immerhin schafft er nun os.h und types.h

Die Leaks hat er mir (als ich jede Datei einzeln bearbeitet habe) nicht gezeigt, was aber auch einfach daran liegen kann, das er nie so weit gekommen ist, weil er vorher an irgendwas verreckt ist.

Vielleicht könntest Du die Ausgabe von Splint uns irgendwie zukommen lassen? (Vielleicht bereinigt um die Funktionsrückgabewert-Sache und andere nebensächliche Dinge). Wär gut, dann hätten wir eine Chance, die Splint-Ergebnisse zu verwerten :)
Erhard Henkes
Mitglied

Benutzerprofil
Anmeldungsdatum: 25.04.2000
Beiträge: 11924
Beitrag Erhard Henkes Mitglied 23:25:24 02.09.2010   Titel:              Zitieren

Zitat:
Sämtliche Log-Funktionen zeigen nur dann was, wenn das Leak tatsächlich eintritt
Das ist korrekt.

Die Ergebnisse von splint bezüglich possible mem leaks würde ich gerne sehen.

_________________
OS-Development-, C++, Win32-API-, MFC-, Chemie-, Robotik- und Flugsimulator-Tutorials
http://www.henkessoft.de/index.htm


Zuletzt bearbeitet von Erhard Henkes am 23:09:47 04.09.2010, insgesamt 1-mal bearbeitet
abc.w
Mitglied

Benutzerprofil
Anmeldungsdatum: 25.04.2008
Beiträge: 1364
Beitrag abc.w Mitglied 22:25:12 04.09.2010   Titel:              Zitieren

Hier, bitte schön (wie gesagt, weiss nicht, welche PrettyOS Version, hatte alles im /tmp Verzeichnis entpackt):
splint schrieb:
/tmp/prettyos/trunk/Source/kernel/list.c: (in function list_Create)
/tmp/prettyos/trunk/Source/kernel/list.c:17:20:
Implicitly only storage hd->tail (type element_t *) not released before
assignment: hd->tail = 0
A memory leak has been detected. Only-qualified storage is not released
before the last reference to it is lost. (Use -mustfreeonly to inhibit
warning)
/tmp/prettyos/trunk/Source/kernel/scheduler.c: (in function scheduler_unblockEvent)
/tmp/prettyos/trunk/Source/kernel/scheduler.c:52:5:
Implicitly only storage blockedTasks->current (type element_t *) not
released before assignment: blockedTasks->current = blockedTasks->begin
A memory leak has been detected. Only-qualified storage is not released
before the last reference to it is lost. (Use -mustfreeonly to inhibit
warning)
/tmp/prettyos/trunk/Source/kernel/storage/ehci.c:60:2:
Fresh storage bar not released before return
A memory leak has been detected. Storage allocated locally is not released
before the last reference to it is lost. (Use -mustfreefresh to inhibit
warning)
/tmp/prettyos/trunk/Source/kernel/storage/ehci.c:44:71:
Fresh storage bar created
/tmp/prettyos/trunk/Source/kernel/storage/flpydsk.c: (in function createFloppy)
/tmp/prettyos/trunk/Source/kernel/storage/flpydsk.c:140:5:
Implicitly only storage fdd->drive.type (type portType_t *) not released
before assignment: fdd->drive.type = &FDD
A memory leak has been detected. Only-qualified storage is not released
before the last reference to it is lost. (Use -mustfreeonly to inhibit
warning)
/tmp/prettyos/trunk/Source/kernel/synchronisation.c: (in function semaphore_create)
/tmp/prettyos/trunk/Source/kernel/synchronisation.c:17:5:
Implicitly only storage obj->resources (type task_t **) not released before
assignment: obj->resources = malloc(sizeof(task_t *) * obj->resCount, 0,
"semaphor-resources")
A memory leak has been detected. Only-qualified storage is not released
before the last reference to it is lost. (Use -mustfreeonly to inhibit
warning)
/tmp/prettyos/trunk/Source/kernel/paging.c:44:41:
Owned storage kernel_pd->pd_phys_addr passed as <error> param:
kdebug (..., kernel_pd->pd_phys_addr)
The owned reference to this storage is transferred to another reference
(e.g., by returning it) that does not have the owned annotation. This may
lead to a memory leak, since the new reference is not necessarily released.
(Use -ownedtrans to inhibit warning)
/tmp/prettyos/trunk/Source/kernel/cdi/cdi_storage.c: (in function cdi_storage_device_init)
/tmp/prettyos/trunk/Source/kernel/cdi/cdi_storage.c:52:2:
Fresh storage partitions not released before return
A memory leak has been detected. Storage allocated locally is not released
before the last reference to it is lost. (Use -mustfreefresh to inhibit
warning)
/tmp/prettyos/trunk/Source/kernel/cdi/cdi_lists.c: (in function cdi_list_pop)
/tmp/prettyos/trunk/Source/kernel/cdi/cdi_lists.c:32:20:
Last reference temp to implicitly only storage list->head not released
before return
A memory leak has been detected. Only-qualified storage is not released
before the last reference to it is lost. (Use -mustfreeonly to inhibit
warning)
/tmp/prettyos/trunk/Source/kernel/cdi/cdi_lists.c:30:5:
Original reference lost
/tmp/prettyos/trunk/Source/kernel/cdi/cdi_lists.c:44:24:
Fresh storage temp not released before return
A memory leak has been detected. Storage allocated locally is not released
before the last reference to it is lost. (Use -mustfreefresh to inhibit
warning)
/tmp/prettyos/trunk/Source/kernel/cdi/cdi.c:34:22:
Fresh storage driver (type struct cdi_driver *) not released before
assignment (in post loop test): driver = cdi_list_get(drivers, j)
A memory leak has been detected. Storage allocated locally is not released
before the last reference to it is lost. (Use -mustfreefresh to inhibit
warning)
/tmp/prettyos/trunk/Source/kernel/cdi/cdi.c:34:22:
Fresh storage driver created
/tmp/prettyos/trunk/Source/kernel/task.c: (in function tasking_install)
/tmp/prettyos/trunk/Source/kernel/task.c:43:5:
Implicitly only storage kernelTask.page_directory (type page_directory_t *)
not released before assignment: kernelTask.page_directory = kernel_pd
A memory leak has been detected. Only-qualified storage is not released
before the last reference to it is lost. (Use -mustfreeonly to inhibit
warning)
/tmp/prettyos/trunk/Source/kernel/keyboard.c:40:5:
Implicitly only storage KQ->pHead (type uint8_t *) not released before
assignment: KQ->pHead = KQ->buffer
A memory leak has been detected. Only-qualified storage is not released
before the last reference to it is lost. (Use -mustfreeonly to inhibit
warning)
/tmp/prettyos/trunk/Source/kernel/filesystem/fsmanager.c: (in function formatPartition)
/tmp/prettyos/trunk/Source/kernel/filesystem/fsmanager.c:31:2:
Fresh storage part not released before return
A memory leak has been detected. Storage allocated locally is not released
before the last reference to it is lost. (Use -mustfreefresh to inhibit
warning)
/tmp/prettyos/trunk/Source/kernel/filesystem/fsmanager.c:29:44:
Fresh storage part created
/tmp/prettyos/trunk/Source/kernel/filesystem/fsmanager.c: (in function fopen)
/tmp/prettyos/trunk/Source/kernel/filesystem/fsmanager.c:43:5:
Implicitly only storage file->volume (type partition_t *) not released
before assignment: file->volume = getPartition(path)
A memory leak has been detected. Only-qualified storage is not released
before the last reference to it is lost. (Use -mustfreeonly to inhibit
warning)
/tmp/prettyos/trunk/Source/kernel/filesystem/initrd.c: (in function ramdisk_install)
/tmp/prettyos/trunk/Source/kernel/filesystem/initrd.c:31:5:
Implicitly only storage RAMdisk.type (type diskType_t *) not released
before assignment: RAMdisk.type = &RAMDISK
A memory leak has been detected. Only-qualified storage is not released
before the last reference to it is lost. (Use -mustfreeonly to inhibit
warning)
/tmp/prettyos/trunk/Source/kernel/video/vbe.c:53:17:
New fresh storage (type task_t *) passed as implicitly temp (not released):
create_vm86_task(((void *)0x121))
A memory leak has been detected. Storage allocated locally is not released
before the last reference to it is lost. (Use -mustfreefresh to inhibit
warning)
/tmp/prettyos/trunk/Source/kernel/video/console.c:34:5:
Implicitly only storage kernelConsole.sp (type struct semaphore *) not
released before assignment: kernelConsole.sp = semaphore_create(1)
A memory leak has been detected. Only-qualified storage is not released
before the last reference to it is lost. (Use -mustfreeonly to inhibit
warning)
/tmp/prettyos/trunk/Source/kernel/kheap.c: (in function heap_install)
/tmp/prettyos/trunk/Source/kernel/kheap.c:50:5:
Only storage assigned to unqualified static:
regions = malloc(0, 0, "heap-start")
The only reference to this storage is transferred to another reference (e.g.,
by returning it) that does not have the only annotation. This may lead to a
memory leak, since the new reference is not necessarily released. (Use
-onlytrans to inhibit warning)
/tmp/prettyos/trunk/Source/kernel/todo_list.c: (in function todoList_create)
/tmp/prettyos/trunk/Source/kernel/todo_list.c:12:5:
Implicitly only storage list->queue (type listHead_t *) not released before
assignment: list->queue = list_Create()
A memory leak has been detected. Only-qualified storage is not released
before the last reference to it is lost. (Use -mustfreeonly to inhibit
warning)
/tmp/prettyos/trunk/Source/kernel/syscall.c: (in function syscall_handler)
/tmp/prettyos/trunk/Source/kernel/syscall.c:136:5:
Only storage currentTask->console assigned to unqualified:
currentConsole = currentTask->console
The only reference to this storage is transferred to another reference (e.g.,
by returning it) that does not have the only annotation. This may lead to a
memory leak, since the new reference is not necessarily released. (Use
-onlytrans to inhibit warning)

Bei mir bricht splint übrigens auch wegen "syntax errors" ab. Ich habe damals auf die Schnelle ein Skript zusammengefrickelt, ungefähr so:
Code:
find . -name *.c -type f > tmp.sh
Code:
find . -name *.c -type f > tmp.sh
Code:
find . -name *.c -type f > tmp.sh
und dann mit dem Editor meiner Wahl splint-Kommandos eingefügt, das geht mit dem Editor meiner Wahl in Sekunden ;)
abc.w
Mitglied

Benutzerprofil
Anmeldungsdatum: 25.04.2008
Beiträge: 1364
Beitrag abc.w Mitglied 17:48:45 05.09.2010   Titel:              Zitieren

Und? Hat splint recht oder ist das alles Quatsch?
Mr X
Mitglied

Benutzerprofil
Anmeldungsdatum: 18.09.2007
Beiträge: 1073
Beitrag Mr X Mitglied 18:35:26 05.09.2010   Titel:              Zitieren

Erhard und ich haben uns das gestern Abend/heute Nacht angesehen und haben keinen Fehler finden können.

Splint sieht in Pointern anscheinend nur einen Sinn: dynamische Speicherallokation. Insofern geht es davon aus, das jede Funktion, die einen Pointer zurückgibt Speicher allokiert hat, was dazu führt, das diese ganzen Meldungen zurückgegeben werden.
Ausserdem scheint es der Meinung zu sein, das man die Member frisch allokierten Speichers erstmal freigeben soll, bevor man sie initialisiert. (Das ist beispielsweise der "Fehler" in list.c Zeile 17)

Trotzdem natürlich danke für den Log, zu überprüfen ob es vielleicht doch Fehler sind hat ja nicht geschadet. :)
abc.w
Mitglied

Benutzerprofil
Anmeldungsdatum: 25.04.2008
Beiträge: 1364
Beitrag abc.w Mitglied 18:43:12 05.09.2010   Titel:              Zitieren

Mr X schrieb:
... zu überprüfen ob es vielleicht doch Fehler sind hat ja nicht geschadet. :)

Nichts zu danken, dafür ist ja dieses Tool da, warnt vor allen möglichen Sachen, ist zwar dumm wie Stroh, hilft aber manchmal :)
C/C++ Forum :: Projekt: OS-Development  ::  C vs C++ bei OSDEV   Auf Beitrag antworten

Zeige alle Beiträge auf einer Seite




Nächstes Thema anzeigen
Vorheriges Thema anzeigen
Sie können keine Beiträge in dieses Forum schreiben.
Sie können auf Beiträge in diesem Forum nicht antworten.
Sie können Ihre Beiträge in diesem Forum nicht bearbeiten.
Sie können Ihre Beiträge in diesem Forum nicht löschen.
Sie können an Umfragen in diesem Forum nicht mitmachen.

Powered by phpBB © 2001, 2002 phpBB Group :: FI Theme

c++.de ist Teilnehmer des Partnerprogramms von Amazon Europe S.à.r.l. und Partner des Werbeprogramms, das zur Bereitstellung eines Mediums für Websites konzipiert wurde, mittels dessen durch die Platzierung von Werbeanzeigen und Links zu amazon.de Werbekostenerstattung verdient werden kann.

Die Vervielfältigung der auf den Seiten www.c-plusplus.de, www.c-plusplus.info, www.c-sar.de, www.c-plusplus.net und www.baeckmann.de enthaltenen Informationen ohne eine schriftliche Genehmigung des Seitenbetreibers ist untersagt (vgl. §4 Urheberrechtsgesetz). Die Nutzung und Änderung der vorgestellten Strukturen und Verfahren in privaten und kommerziellen Softwareanwendungen ist ausdrücklich erlaubt, soweit keine Rechte Dritter verletzt werden. Der Seitenbetreiber übernimmt keine Gewähr für die Funktion einzelner Beiträge oder Programmfragmente, insbesondere übernimmt er keine Haftung für eventuelle aus dem Gebrauch entstehenden Folgeschäden.