Forum: PC-Programmierung Malloc - Fehler


von Daniel S. (dani2304)


Lesenswert?

Hallo,
ich habe ein Problem mit der dynamischen Speicherverwaltung. Es 
reserviert mehr Speicherplatz als ich vorhabe
1
#include <stdio.h>
2
#include <stdlib.h>
3
#define GROESSE_FELD 4
4
#define DIM_ZEILE GROESSE_FELD * 2+1
5
#define DIM_SPALTE GROESSE_FELD * 2+1
6
7
8
void spielGeruest(char **spielfeld){
9
int i=0, j=0;
10
11
for (i=0;i<(DIM_ZEILE); i++){
12
    for(j=0;j<(DIM_SPALTE);j++){
13
        if(!(i%2)){
14
            if(!(j%2)){
15
                spielfeld[i][j]='|';
16
        }
17
        else{
18
            spielfeld[i][j]='-';
19
20
        }
21
        }
22
        else{
23
            if(!(j%2)){
24
                spielfeld [i][j]='|';
25
            }
26
            else{
27
                spielfeld [i][j]='x';
28
            }
29
        }
30
    }
31
}
32
}
33
34
void ausgabeSpielfeld(char **spielfeld){
35
36
}
37
int main(){
38
    char **Feld;
39
    int i;
40
    Feld=(char**)malloc(sizeof(char*)* DIM_ZEILE);
41
    for(i=0;i<DIM_SPALTE;i++){
42
        Feld[i]=(char*)malloc(sizeof(char)* DIM_SPALTE);
43
}
44
spielGeruest(Feld);
45
printf("%s",*(Feld+1));
46
}

Zusätzlich zum String gibt er mir noch mehr Zeichen aus.

Warum?

MfG

von AVerr (Gast)


Lesenswert?

Fehlende Nullterminierung

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Daniel S. schrieb:
> Feld[i]=(char*)malloc(sizeof(char)* DIM_SPALTE);

Das macht nicht das, was Du erwartest.

> sizeof(char)* DIM_SPALTE

Wieviel mag das sein?

> #define GROESSE_FELD 4
> #define DIM_SPALTE GROESSE_FELD * 2+1

Also:

> sizeof (char)  4  2 + 1


Durch die Verwendung von Klammern im #define-Ausdruck ließe sich das 
Problem beseitigen.


Davon abgesehen

> Feld=(char**)malloc(sizeof(char*)* DIM_ZEILE);
> for(i=0;i<DIM_SPALTE;i++){
>   Feld[i]=(char*)malloc(sizeof(char)* DIM_SPALTE);

ist hier das Schleifenabbruchkriterium falsch, da sollte nicht 
DIM_SPALTE, sondern DIM_ZEILE stehen. Das macht hier zwar nichts, da 
beide gleich groß sind, aber wenn sie es nicht mehr sind (weil die 
Feldgrößen geändert werden), knallts.


Im übrigen wird C-Sourcecode durchaus lesbarer, wenn man an sinnvollen 
Stellen Leerzeichen zur Trennung verwendet:

> Feld = (char **) malloc(sizeof (char *) * DIM_ZEILE);
> for (i = 0; i < DIM_SPALTE; i++)
> {
>   Feld[i] = (char *) malloc(sizeof (char) * DIM_SPALTE);

Die beiden Typecasts sind in C übrigens überflüssig; malloc gibt void* 
zurück, das lässt sich beliebigen Pointertypen zuweisen.

von Rolf M. (rmagnus)


Lesenswert?

Und sizeof(char) ist per Definition immer 1.
Generell bietet es sich aber an, bei Malloc einfach das Zeigerziel des 
Ergebnisses für die Größe herzunehmen:
1
Feld = malloc(DIM_ZEILE * sizeof *Feld);
2
3
Feld[i] = malloc(DIM_SPALTE * sizeof **Feld);

So sind sämtliche Größen der Typen bei den mallocs nur noch davon 
abhängig, wie Feld definiert ist statt "hart codiert". Solltest du 
später mal auf die Idee kommen, aus den chars doch shorts oder gar 
structs zu machen, passt der Code ohne Änderung.

von Kaj (Gast)


Lesenswert?

Daniel S. schrieb:
> Feld=(char**)malloc(sizeof(char*)* DIM_ZEILE);
In C soll man den Rueckgabewert von malloc nicht casten!

von tictactoe (Gast)


Lesenswert?

Das hier
> #define DIM_ZEILE GROESSE_FELD * 2+1

und das hier
>     Feld=(char**)malloc(sizeof(char*)* DIM_ZEILE);

passt nicht gut zusammen.

Man schreibt die Klammern im #define (und nicht dort, wo die Konstante 
benutzt wird) und zwar genau deshalb, damit der Wert nicht den 
Vorrangregeln von Operatoren gestört wird:
1
sizeof(char*)* GROESSE_FELD * 2+1
ist nämlich was ganz anderes als
1
sizeof(char*)* (GROESSE_FELD * 2+1)

von Daniel A. (daniel-a)


Lesenswert?

Tip: Man kann in c auch solche Dinge tun:
1
#include <stdio.h>
2
3
int main(){
4
  printf("%u\n",sizeof(int[5][2]));
5
  return 0;
6
}
Oder sowas:
1
#include <stdio.h>
2
3
int main(){
4
  const int a=5;
5
  const int b=2;
6
  printf("%u\n",sizeof(int[a][b]));
7
  return 0;
8
}

von Daniel A. (daniel-a)


Lesenswert?

Noch ein Trick, den ich gerne anwende:
1
#include <stdio.h>
2
3
void func( const int x, const int y, int buf[y][x] ){
4
  buf[1][3] = 42;
5
}
6
7
int main(){
8
  const int x=5, y=2;
9
  int buf[y][x];
10
  func(x,y,buf);
11
  printf("%d\n",buf[1][3]);
12
  return 0;
13
}

Die Vorteile hier sind, dass man sich nirgens verrechnen kann und es 
kein malloc gibt das fehlschlagen könnte. Ein nachteil ist, dass es yu 
einem Stackoverflow kommen kann, wenn buf zu gross ist.

von Daniel S. (dani2304)


Lesenswert?

Okay perfekt. Vielen Dank schon einmal für eure umfassende Hilfe :). 
Habe den Großteil schon ausgebessert.

Eine Frage hätte ich jedoch noch. Und zwar will ich in einem String den 
Wert einer Variablen abspeichern. Wie geht das?

Kenne nur die Möglichkeiten mit "..." und '...' konstante Werte 
abzuspeichern. Aber sowas wie str1[0][0]=x;
geht nicht ....

von Markus L. (rollerblade)


Lesenswert?

Guckst Du nach sprintf.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.