OVH Cloud OVH Cloud

Question sur realloc

67 réponses
Avatar
Kevin Denis
Bonjour,

j'ai une question sur realloc:
$ cat testrealloc.c
#include <stdio.h>
#include <stdlib.h>

int main(void){
char * c=NULL;
c=malloc(8);
if (c == NULL) return -1;
c="abcdefgh";
printf("valeur du pointeur: %d\r\n",c);
printf("valeur de c: %s\r\n",c);
c=realloc(c,16);
return 0;
}
$ gcc -Wall -o testrealloc testrealloc.c
testrealloc.c: In function 'main':
testrealloc.c:9: attention : format '%d' expects type 'int', but argument 2
has type 'char *'
$ ./testrealloc
valeur du pointeur: 134514000
valeur de c: abcdefgh
Erreur de segmentation

Ma question est: pourquoi le realloc segfaulte?
Merci
--
Kevin

10 réponses

3 4 5 6 7
Avatar
-ed-
On 5 mai, 12:32, Alexandre Bacquart wrote:
On 05/05/2011 11:08 AM, Kevin Denis wrote:

> quel est le type de sizeof?

Le type ? sizeof n'a pas de type, ce n'est pas une variable.

sizeof est un opérateur, au même titre que + ou *.




et comme tout opérateur, il retourne une valeur typée. Ici, le type
retourné est size_t, c'est à dire un entier non signé.
Avatar
-ed-
On 5 mai, 11:04, Kevin Denis wrote:

Ok. Le malloc n'est pas appelé car la chaine est dans le code du progra mme..




Surtout, le malloc() n'est pas appéléparce que personne ne l'a apelé.
En C standard, les apaels à maloc() sont explicites.On est certain que

ni
char *s="abcd";
ni
char s[]="abcd";
n’appelleront malloc().

Il n'y a donc aucun moyen d'utiliser realloc() sur ces chaines.

Par contre, en POSIX, il existe une fonction strdup(), qui, et il FAUT
le savoir, utilise malloc().

char *s = strdup("abcd");

on peut donc ensuite agrandir la chaîne comme ceci :

char s2[]="abcdefgh";

s = realloc(s, sizeof s2);

mais la copie de s2 au bout de s n'est pas automatique, il faut
ensuite utiliser strcat() :

strcat (s, s2);

en dans tous les cas, libérer s avec free(), quand c'est terminé.
Avatar
Alexandre Bacquart
On 05/06/2011 10:10 AM, Marc Boyer wrote:
Le 05-05-2011, Alexandre Bacquart a écrit :
Certes, tout ceci est fort joli (et réel)... il y a tellement de façons
d'optimiser. Mais ce qui m'intéresse plus particulièrement, c'est la
valeur pédagogique de mon propos initial. En quoi mon explication
tendrait à mettre le doute dans la tête l'OP, voire à lui inculquer une
fausse conception (pour ce qu'il a besoin de savoir pour l'instant) ?



Ayant enseigné le C un certain nombre d'années, j'aurais tendance à
dire que ton propos entrainait une confusion, car il supposait que
dans l'écriture
char str[]= "abdcef";
il y a *deux* objets (str, et "abcdef"), alors qu'il n'y en a qu'un.
Alors que dans
char* ptr = "abcdef";
il y a bien deux objets, prt et "abcdef".



Qu'on me permette de me défendre (Marc Espie n'est d'ailleurs pas
intervenu sur ce point). Voici mon propos initial à ce sujet :

char *str = "abcdefgh";

Il y a deux choses : la chaîne "abcdefgh" (que tu ne peux pas modifier) et le pointeur str (initialisé sur cette chaîne). Alors que dans :

char tab[] = "abcdefgh";

Il n'y a que la chaîne (toujours pas modifiable) *identifiée* par s. Aucun pointeur. Ici, tab n'est pas un pointeur, mais identifie la chaîne.



Cela ne semble pas être en contradiction avec ce que tu viens de dire.
J'ai même appuyé cette notion par la suite dans un autre message en des
termes quasi identiques aux tiens :

Mon intention était plutôt de faire comprendre à l'OP que la différence
entre les 2 expressions était le nombre d'objets créés (2 dans le cas
char*, 1 dans le cas char[]).



Ce à quoi Marc Espie a jugé bon de répondre que c'était faux (et, en
substance, "qu'est-ce qu'un objet créé ?"). Qui a raison ?

Qu'on me comprenne bien, je ne cherche pas à troller inutilement ici,
mais à parfaire ma capacité à expliquer des mécanismes de C (tout en me
gardant bien de tenter de saccager le fond de commerce des enseignants :)).

En fait, Marc est intervenu (peut-être à juste titre, c'est ce je
cherchais à savoir) sur le fait que je qualifiais un tableau terminé par
'' de chaîne (à l'exécution). Comme il le dit assez bien, c'est un
problème de vocabulaire.

Autre chose : généralement, je préfère éviter le terme de tableau quand
je m'adresse à des débutants en C. Je sais bien que ce terme est adéquat
dans le cadre de la norme C, mais bien souvent, les débutants en C ont
une conception des tableaux autre que celle de la norme C et ils s'y
cassent les dents assez vite. D'où mon hésitation à utiliser ce terme,
en tous cas, pas sans développer le propos. Ca complique pas mal la
nécessité d'être concis pour ne pas l'embrouiller.



Comment evites-tu de parler de tableau ?



Du mieux que je peux, habituellement :) Mais Antoine et Marc m'ont
convaincu qu'il est plus difficile d'éviter d'en parler.


--
Alex
Avatar
espie
In article ,
-ed- wrote:
Par contre, en POSIX, il existe une fonction strdup(), qui, et il FAUT
le savoir, utilise malloc().



Non.

La description de POSIX te dit que le resultat de strdup() peut etre passe
a free(). Ce qui n'est pas strictement la meme chose.


Pas du tout bizarrement, strdup() est dans POSIX, mais pas dans ISO C.

C'est totalement intentionnel: strdup() traine dans les systemes depuis avant
la normalisation du C... et a ete egalement incorporee en C++. Du coup, sur
des vieux systemes, tu ne sais jamais trop si strdup() existe, ni si elle
utilise un equivalent de malloc() ou de new en interne.
(et de plus, c'est a peu pres la seule fonction associee a string.h qui fait
de la gestion memoire).
Avatar
Jean-Marc Bourguet
(Marc Espie) writes:

C'est totalement intentionnel: strdup() traine dans les systemes depuis avant
la normalisation du C... et a ete egalement incorporee en C++.



strdup n'est pas plus standardisee en C++ qu'en C.

A+

--
Jean-Marc
FAQ de fclc: http://www.levenez.com/lang/c/faq
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Avatar
Lucas Levrel
Le 6 mai 2011, Kevin Denis a écrit :

Le 05-05-2011, Marc Espie a écrit :
Dans char *s = "coucou"; la valeur pointee est constante.
Dans char t[] = "coucou"; c'est l'adresse qui pointe qui est constante.



Mais dans char t[] = "coucou"; l'adresse qui pointe est constante, c'est
à dire &t donc. Je ne peux pas modifier la valeur de &t.



Non, ce que dit Marc c'est que tu ne peux pas modifier la valeur de t :
* interdit :
char t[]="coucou";
char toto='A';
t=&toto;

* autorisé :
char *s="coucou";
char toto='A';
s=&toto;

--
LL
Avatar
Pierre Maurette
Lucas Levrel, le 5/7/2011 a écrit :

[...]

char *s="coucou";



Et pourquoi ce ne serait pas mieux d'écrire:

char* s = "coucou";

--
Pierre Maurette
Avatar
Samuel DEVULDER
Le 07/05/2011 20:17, Pierre Maurette a écrit :
Lucas Levrel, le 5/7/2011 a écrit :

[...]

char *s="coucou";





Ici je lis que *s est un char.

Et pourquoi ce ne serait pas mieux d'écrire:

char* s = "coucou";



Ici je lis que s est un char*.

Bon c'est pareil. L'un est l'autre se lisent et s'utilisent aussi
facilement. Perso j'utilise assez la 1ere écriture (avec *s) quand il
s'agit de décrire des pointeurs sur pointeurs de trucs (genres pointeur
sur fonction prenant des pointeurs sur int et retournant un tableau de
fonctions retournant elles mêmes des pointeurs sur int).

Mais ces cas tordus sont rares, et si on veut être compris de tous il
est parfois utile d'ajouter des typedefs pour avoir des combinaisons
simples de types plutot qu'une grosse combinaison complexe de type simples.

sam.
Avatar
Xavier Roche
Le 07/05/2011 20:17, Pierre Maurette a écrit :
Et pourquoi ce ne serait pas mieux d'écrire:
char* s = "coucou";



Quand à chipoter, ce qui manque surtout, c'est le "const":
const char* s = "coucou";
Avatar
Pierre Maurette
Xavier Roche, le 5/7/2011 a écrit :
Le 07/05/2011 20:17, Pierre Maurette a écrit :
Et pourquoi ce ne serait pas mieux d'écrire:
char* s = "coucou";



Quand à chipoter, ce qui manque surtout, c'est le "const":
const char* s = "coucou";



Oui. J'ai perdu du temps avec ce bordel. s est un /char étoile/ non
modifiable. En fait un pointeur sur une chaîne en dur. Un littéral
chaîne.
Le littéral chaîne n'existe que pendant les instants de la compilation.

--
Pierre Maurette
3 4 5 6 7