[C] malloc
Fermé
Onde2Choc
Messages postés
299
Date d'inscription
vendredi 6 août 2004
Statut
Membre
Dernière intervention
24 février 2006
-
30 août 2004 à 08:23
Jolkdarr - 2 sept. 2004 à 20:19
Jolkdarr - 2 sept. 2004 à 20:19
A voir également:
- Malloc invalid initializer
- Invalid signature detected check secure boot policy in setup - Forum Windows 10
- % Invalid input detected at '^' marker. ✓ - Forum CISCO
- The input value is invalid. - Forum Javascript
- Could not do normal boot invalid kernel length - Forum Samsung
- Invalid system disk - Forum Windows
19 réponses
Hello !
Ecrire :
mon_type* X = (mon_type*) malloc(sizeof(mon_type));
n'est plus nécessaire depuis le C standard puisque celui-ci spécifie qu'un compilateur peut convertir un pointeur void* en un autre pointeur. Cependant, le code donné est plus portable puisqu'il fonctionne avec :
- un compilateur standard C,
- un compilateur non standard C,
- un compilateur non standard C qui déclare char* malloc(),
- un compilateur C++, cerise sur le gâteau ;)
Il est à noter qu'un compilateur C++ standard refuse une conversion de void* vers un pointeur typé.
A propos de la conversion de pointeurs, il ne faut pas en sous-estimer les dangers. Les conversions de pointeurs demandent beaucoup de prudence car un compilateur C ne fera aucun contrôle.
Exemple 1 : bug1.c
#include <stdio.h>
#include <stdlib.h>
typedef struct t
{
int X[10];
} t;
t T0 = { { 9 } };
int main()
{
char* P1 = (char*) malloc(sizeof(char));
char* P2 = (char*) malloc(sizeof(char));
/* conversion incorrecte */
t* Q = P1;
printf("%d\n", *P1 = 1);
printf("%d\n", *P2 = 1);
*Q = T0; /* BUG */
printf("%d\n", *P1);
printf("%d\n", *P2);
free(P2);
free(P1);
return 0;
}
---
Dans cet exemple, on convertit un char* en t* ce qui entraîne une catastrophe au niveau de la mémoire...
---
Exemple 2 : bug2.c
#include <stdio.h>
#include <stdlib.h>
int main()
{
char* Cp = (char*) 1;;
int* Ip = Cp;
printf("Cp = %p\n", Cp);
printf("Ip = %p\n", Ip);
printf("*Cp = %d\n", *Cp);
printf("*Ip = %d\n", *Ip);
return 0;
}
---
Dans cet exemple, on convertit un (char*) en (int*) ce qui provoque un problème d'alignement et de la même manière, la sanction ne se fait pas attendre...
---
En résumé, quand on fait une conversion de pointeur en pointeur, il faut se demander :
- si il n'y a pas une solution plus élégante et moins dangereuse,
- si le pointeur non typé (void*) est réellement convertible en un pointeur typé. Il se peut que le programme n'ait pas les éléments pour le déterminer.
C++ est beaucoup plus contraignant sur la question des conversions. Par exemple :
int main()
{
char(*P10) [10];
char(*P5) [5];
P5 = P10; // NOT OK => erreur de compilation
return 0;
}
// Dans cet exemple, le compilateur refuse de convertir un pointeur sur un tableau de char en un pointeur de chars uniquement parce que les tableaux n'ont pas la même taille.
Take care !
Ecrire :
mon_type* X = (mon_type*) malloc(sizeof(mon_type));
n'est plus nécessaire depuis le C standard puisque celui-ci spécifie qu'un compilateur peut convertir un pointeur void* en un autre pointeur. Cependant, le code donné est plus portable puisqu'il fonctionne avec :
- un compilateur standard C,
- un compilateur non standard C,
- un compilateur non standard C qui déclare char* malloc(),
- un compilateur C++, cerise sur le gâteau ;)
Il est à noter qu'un compilateur C++ standard refuse une conversion de void* vers un pointeur typé.
A propos de la conversion de pointeurs, il ne faut pas en sous-estimer les dangers. Les conversions de pointeurs demandent beaucoup de prudence car un compilateur C ne fera aucun contrôle.
Exemple 1 : bug1.c
#include <stdio.h>
#include <stdlib.h>
typedef struct t
{
int X[10];
} t;
t T0 = { { 9 } };
int main()
{
char* P1 = (char*) malloc(sizeof(char));
char* P2 = (char*) malloc(sizeof(char));
/* conversion incorrecte */
t* Q = P1;
printf("%d\n", *P1 = 1);
printf("%d\n", *P2 = 1);
*Q = T0; /* BUG */
printf("%d\n", *P1);
printf("%d\n", *P2);
free(P2);
free(P1);
return 0;
}
---
Dans cet exemple, on convertit un char* en t* ce qui entraîne une catastrophe au niveau de la mémoire...
---
Exemple 2 : bug2.c
#include <stdio.h>
#include <stdlib.h>
int main()
{
char* Cp = (char*) 1;;
int* Ip = Cp;
printf("Cp = %p\n", Cp);
printf("Ip = %p\n", Ip);
printf("*Cp = %d\n", *Cp);
printf("*Ip = %d\n", *Ip);
return 0;
}
---
Dans cet exemple, on convertit un (char*) en (int*) ce qui provoque un problème d'alignement et de la même manière, la sanction ne se fait pas attendre...
---
En résumé, quand on fait une conversion de pointeur en pointeur, il faut se demander :
- si il n'y a pas une solution plus élégante et moins dangereuse,
- si le pointeur non typé (void*) est réellement convertible en un pointeur typé. Il se peut que le programme n'ait pas les éléments pour le déterminer.
C++ est beaucoup plus contraignant sur la question des conversions. Par exemple :
int main()
{
char(*P10) [10];
char(*P5) [5];
P5 = P10; // NOT OK => erreur de compilation
return 0;
}
// Dans cet exemple, le compilateur refuse de convertir un pointeur sur un tableau de char en un pointeur de chars uniquement parce que les tableaux n'ont pas la même taille.
Take care !
(person*) est un cast. Tu devrais retrouvé cela dans ton livre.
Sinon pour calloc, il initialise la mémoire, càd qu'il met à zéro les octets qu'il a alloué.
Sinon pour calloc, il initialise la mémoire, càd qu'il met à zéro les octets qu'il a alloué.
Onde2Choc
Messages postés
299
Date d'inscription
vendredi 6 août 2004
Statut
Membre
Dernière intervention
24 février 2006
4
30 août 2004 à 11:24
30 août 2004 à 11:24
AAAaaah je comprends... On caste le pointeur pour qu'il pointe sur une structure de type person... Oki merci...
Quant à calloc, tu veux dire qu'il attribue à chaque octet la valeur 0 ?
BOOM !
Laissez se propager l'onde de choc...
Quant à calloc, tu veux dire qu'il attribue à chaque octet la valeur 0 ?
BOOM !
Laissez se propager l'onde de choc...
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question
Hello !
Les fonctions d'allocation mémoire du C retournent toutes un pointeur non typé (void*). Il te faut à chaque fois, le convertir en pointeur typé de la manière suivante :
mon_type* X = (mon_type*) malloc(sizeof(mon_type));
calloc alloue de la mémoire pour un tableau de n éléments qu'il initialise à 0. Exemple :
mon_type* A = (mon_type*) calloc(sizeof(mon_type), 10);
/* allocation pour 10 éléments mon_type */
Take care !
Les fonctions d'allocation mémoire du C retournent toutes un pointeur non typé (void*). Il te faut à chaque fois, le convertir en pointeur typé de la manière suivante :
mon_type* X = (mon_type*) malloc(sizeof(mon_type));
calloc alloue de la mémoire pour un tableau de n éléments qu'il initialise à 0. Exemple :
mon_type* A = (mon_type*) calloc(sizeof(mon_type), 10);
/* allocation pour 10 éléments mon_type */
Take care !
Mauvaise utilisation du cast. Quelque soit le type une adresse est une adresse. Le cast sert à convertir des types mais que quand cela engendre un dépassement mémoire.
exemple:
int x = 15;
char c;
c = (char)x;
Convertir un pointeur en pointeur est trivial.
exemple:
int x = 15;
char c;
c = (char)x;
Convertir un pointeur en pointeur est trivial.
Onde2Choc
Messages postés
299
Date d'inscription
vendredi 6 août 2004
Statut
Membre
Dernière intervention
24 février 2006
4
31 août 2004 à 08:38
31 août 2004 à 08:38
Hum... Et est-ce qu'on peut caster une variable en pointeur ?
BOOM !
Laissez se propager l'onde de choc...
BOOM !
Laissez se propager l'onde de choc...
Oui on peut "caster" un char int etc en pointeur car en réalité un pointeur est équivalent à un unsigned int.
Onde2Choc
Messages postés
299
Date d'inscription
vendredi 6 août 2004
Statut
Membre
Dernière intervention
24 février 2006
4
1 sept. 2004 à 08:39
1 sept. 2004 à 08:39
Le C++ est un langage chieur ! :-D Mais j'ai compris, j'éviterais la conversion de pointeurs...
BOOM !
Laissez se propager l'onde de choc...
BOOM !
Laissez se propager l'onde de choc...
Canard007
Messages postés
5929
Date d'inscription
mercredi 26 mai 2004
Statut
Contributeur
Dernière intervention
18 septembre 2009
215
1 sept. 2004 à 10:18
1 sept. 2004 à 10:18
Quel debat pour une simple alocation
COIN!
COIN!
Onde2Choc
Messages postés
299
Date d'inscription
vendredi 6 août 2004
Statut
Membre
Dernière intervention
24 février 2006
4
1 sept. 2004 à 12:31
1 sept. 2004 à 12:31
Ben, au début je pensait mettre ce post dans le café mais comme on n'y boit pas et que il y a de la prog dedans alors je l'ai mis ici...
BOOM !
Laissez se propager l'onde de choc...
BOOM !
Laissez se propager l'onde de choc...
Hello !
Bin, je m'enflammerais volontiers pour Ada 95 aussi, mais faut reconnaître qu'à moins de travailler pour les militaires ou les transports, ce langage n'a plus la cote.
Pour en revenir à C++, qui connait et utilise les pointeurs automatiques (auto_ptr<>) ?
Bin, je m'enflammerais volontiers pour Ada 95 aussi, mais faut reconnaître qu'à moins de travailler pour les militaires ou les transports, ce langage n'a plus la cote.
Pour en revenir à C++, qui connait et utilise les pointeurs automatiques (auto_ptr<>) ?
Canard007
Messages postés
5929
Date d'inscription
mercredi 26 mai 2004
Statut
Contributeur
Dernière intervention
18 septembre 2009
215
2 sept. 2004 à 10:36
2 sept. 2004 à 10:36
J'ai bossé un peu pour les militaires ... et même chez eux sa tombe un peu un desuetude...^^
COIN!
COIN!
Onde2Choc
Messages postés
299
Date d'inscription
vendredi 6 août 2004
Statut
Membre
Dernière intervention
24 février 2006
4
2 sept. 2004 à 08:14
2 sept. 2004 à 08:14
Ada 95 fait quoi comme langage ? J'en ai entendu parler sans jamais en voir ni en lire...
BOOM !
Laissez se propager l'onde de choc...
BOOM !
Laissez se propager l'onde de choc...
Onde2Choc
Messages postés
299
Date d'inscription
vendredi 6 août 2004
Statut
Membre
Dernière intervention
24 février 2006
4
2 sept. 2004 à 13:52
2 sept. 2004 à 13:52
Mais on peut faire quoi avec Ada95 ? En quoi est-ce que ce langage est spécialisé ?
BOOM !
Laissez se propager l'onde de choc...
BOOM !
Laissez se propager l'onde de choc...
Hello !
Ada 95 est un langage général comme C ou C++. Il prend en charge la mémoire (comme Java) et possède des mécanismes pour gérer le multitâches (type rendez-vous). Il est très utilisé pour les gros systèmes car très fiable et très sécurisé. Il existe des compilateurs gratuits (sur Linux : GNAT par exemple).
T'en a jamais vu ?
Tiens, un exemple, rien que pour toi :
generic
type T is private;
package gestion_de_liste is
-- type acces pour le chainage :
type noeud;
type acces_noeud is access Noeud;
-- type pour définir un noeud (élement d'une liste) :
type noeud is record
Suivant : Acces_noeud := null; -- acces au noeud suivant
Donnee : T; -- donnée utile
end record;
-- type pour définir un objet liste gérant une liste d'éléments de type T :
type Liste is record
Tete : acces_noeud := null;
Queue : acces_noeud := null;
Nombre_elements : natural := 0;
end record;
-- type pour accéder à un objet liste :
type acces_liste is access Liste;
-- exceptions :
liste_non_vide : exception;
-- constructeur/destructeur :
procedure creer_liste(Une_liste : out acces_liste);
procedure supprimer_liste(Une_liste : in out acces_liste);
-- gestion de la liste :
procedure inserer(Une_liste : in out acces_liste; Element : in T);
procedure extraire(Une_liste : in out acces_liste; Element : out T);
function est_vide(Une_liste : in acces_liste) return boolean;
end;
package body gestion_de_liste is
procedure creer_liste(Une_liste : out acces_liste) is
begin
Une_liste := new Liste;
end;
procedure supprimer_liste(Une_liste : in out acces_liste) is
begin
if Une_liste.Tete /= null then
-- raise liste_non_vide;
null;
end if;
Une_liste := null;
end;
procedure inserer(Une_liste : in out acces_liste; Element : in T) is
Nouveau_noeud : acces_noeud := new noeud'(Suivant => null, Donnee => Element);
begin
if Une_liste.Tete = null then
Une_liste.Tete := Nouveau_noeud;
Une_liste.Queue := Une_liste.Tete;
else
Une_liste.Queue.Suivant := Nouveau_noeud;
Une_liste.Queue := Nouveau_noeud;
end if;
Une_liste.Nombre_elements := Une_liste.Nombre_elements + 1;
end;
procedure extraire(Une_liste : in out acces_liste; Element : out T) is
begin
-- ### A COMPLETER
if Une_liste.Nombre_elements = 0 then
null;
else
Element := Une_liste.Queue.Donnee;
end if;
end;
function est_vide(Une_liste : in acces_liste) return boolean is
begin
return Une_liste.Nombre_elements = 0;
end;
end;
package exemple is
generic
type T is private;
procedure swap(V1, V2 : in out T);
end;
package body exemple is
procedure swap(V1, V2 : in out T) is
Temporaire : T := V1;
begin
V1 := V2;
V2 := Temporaire;
end swap;
end;
with text_io;
with exemple;
with gestion_de_liste;
procedure main is
X1 : integer := 1;
X2 : integer := 2;
procedure swap_integer is new Exemple.swap(integer);
package int_io is new text_io.integer_io(integer);
package liste_integer is new gestion_de_liste(integer);
package liste_float is new gestion_de_liste(float);
Une_liste_entiers : liste_integer.acces_liste;
begin
liste_integer.creer_liste(Une_liste_entiers);
liste_integer.inserer(Une_liste_entiers, 10);
liste_integer.supprimer_liste(Une_liste_entiers);
text_io.put("X1 = ");
int_io.put(X1);
Text_io.new_line;
text_io.put("X2 = ");
int_io.put(X2);
Text_io.new_line;
swap_integer(X1, X2);
text_io.put_line("SWAP");
text_io.put("X1 = ");
int_io.put(X1);
Text_io.new_line;
text_io.put("X2 = ");
int_io.put(X2);
Text_io.new_line;
end;
end package;
Ada 95 est un langage général comme C ou C++. Il prend en charge la mémoire (comme Java) et possède des mécanismes pour gérer le multitâches (type rendez-vous). Il est très utilisé pour les gros systèmes car très fiable et très sécurisé. Il existe des compilateurs gratuits (sur Linux : GNAT par exemple).
T'en a jamais vu ?
Tiens, un exemple, rien que pour toi :
generic
type T is private;
package gestion_de_liste is
-- type acces pour le chainage :
type noeud;
type acces_noeud is access Noeud;
-- type pour définir un noeud (élement d'une liste) :
type noeud is record
Suivant : Acces_noeud := null; -- acces au noeud suivant
Donnee : T; -- donnée utile
end record;
-- type pour définir un objet liste gérant une liste d'éléments de type T :
type Liste is record
Tete : acces_noeud := null;
Queue : acces_noeud := null;
Nombre_elements : natural := 0;
end record;
-- type pour accéder à un objet liste :
type acces_liste is access Liste;
-- exceptions :
liste_non_vide : exception;
-- constructeur/destructeur :
procedure creer_liste(Une_liste : out acces_liste);
procedure supprimer_liste(Une_liste : in out acces_liste);
-- gestion de la liste :
procedure inserer(Une_liste : in out acces_liste; Element : in T);
procedure extraire(Une_liste : in out acces_liste; Element : out T);
function est_vide(Une_liste : in acces_liste) return boolean;
end;
package body gestion_de_liste is
procedure creer_liste(Une_liste : out acces_liste) is
begin
Une_liste := new Liste;
end;
procedure supprimer_liste(Une_liste : in out acces_liste) is
begin
if Une_liste.Tete /= null then
-- raise liste_non_vide;
null;
end if;
Une_liste := null;
end;
procedure inserer(Une_liste : in out acces_liste; Element : in T) is
Nouveau_noeud : acces_noeud := new noeud'(Suivant => null, Donnee => Element);
begin
if Une_liste.Tete = null then
Une_liste.Tete := Nouveau_noeud;
Une_liste.Queue := Une_liste.Tete;
else
Une_liste.Queue.Suivant := Nouveau_noeud;
Une_liste.Queue := Nouveau_noeud;
end if;
Une_liste.Nombre_elements := Une_liste.Nombre_elements + 1;
end;
procedure extraire(Une_liste : in out acces_liste; Element : out T) is
begin
-- ### A COMPLETER
if Une_liste.Nombre_elements = 0 then
null;
else
Element := Une_liste.Queue.Donnee;
end if;
end;
function est_vide(Une_liste : in acces_liste) return boolean is
begin
return Une_liste.Nombre_elements = 0;
end;
end;
package exemple is
generic
type T is private;
procedure swap(V1, V2 : in out T);
end;
package body exemple is
procedure swap(V1, V2 : in out T) is
Temporaire : T := V1;
begin
V1 := V2;
V2 := Temporaire;
end swap;
end;
with text_io;
with exemple;
with gestion_de_liste;
procedure main is
X1 : integer := 1;
X2 : integer := 2;
procedure swap_integer is new Exemple.swap(integer);
package int_io is new text_io.integer_io(integer);
package liste_integer is new gestion_de_liste(integer);
package liste_float is new gestion_de_liste(float);
Une_liste_entiers : liste_integer.acces_liste;
begin
liste_integer.creer_liste(Une_liste_entiers);
liste_integer.inserer(Une_liste_entiers, 10);
liste_integer.supprimer_liste(Une_liste_entiers);
text_io.put("X1 = ");
int_io.put(X1);
Text_io.new_line;
text_io.put("X2 = ");
int_io.put(X2);
Text_io.new_line;
swap_integer(X1, X2);
text_io.put_line("SWAP");
text_io.put("X1 = ");
int_io.put(X1);
Text_io.new_line;
text_io.put("X2 = ");
int_io.put(X2);
Text_io.new_line;
end;
end package;
blurk
Messages postés
486
Date d'inscription
vendredi 16 avril 2004
Statut
Membre
Dernière intervention
15 mars 2009
160
2 sept. 2004 à 20:10
2 sept. 2004 à 20:10
new = (person*)malloc( sizeof(person));
Person étant le nom de la structure et new un pointeur vers le nouvel élément. Mais à quoi peut bien servir le (person*) devant malloc ? Jusqu'ici j'aurais procédé comme ça : new= malloc( sizeof(person));
c'est new le nom du pointeur sur structure. On dit aussi l'instance sur structure de type person (attention, new est un mot réservé pour le c++ et il est à éviter)
person c'est le type de la structure, et même le type de variable,
au même titre que char ou int.
ce n'est pas un cast, il n'est pas question d'attribuer le conternu d'une variable à une variable d'un autre type. (d'accord avec guki)
dans un malloc, on précise toujours l'instance et le type, c'est le strict minimum pour distinguer une variable de manière unique.
exemple "la voiture immatriculée 999 xxx 99" où voiture est le type et 999 xxx 99 est l'instance de type voiture, c'est à dire son nom.
Impossible de simplifier plus !
¤
Person étant le nom de la structure et new un pointeur vers le nouvel élément. Mais à quoi peut bien servir le (person*) devant malloc ? Jusqu'ici j'aurais procédé comme ça : new= malloc( sizeof(person));
c'est new le nom du pointeur sur structure. On dit aussi l'instance sur structure de type person (attention, new est un mot réservé pour le c++ et il est à éviter)
person c'est le type de la structure, et même le type de variable,
au même titre que char ou int.
ce n'est pas un cast, il n'est pas question d'attribuer le conternu d'une variable à une variable d'un autre type. (d'accord avec guki)
dans un malloc, on précise toujours l'instance et le type, c'est le strict minimum pour distinguer une variable de manière unique.
exemple "la voiture immatriculée 999 xxx 99" où voiture est le type et 999 xxx 99 est l'instance de type voiture, c'est à dire son nom.
Impossible de simplifier plus !
¤