Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

char* (chaine type c)

13 réponses
Avatar
pasdespam
bonjour,

je tente d'utiliser CURL.

la plupart (et notament curl_easy_setopt) reclament des char* c
(terminés par \0) en parametre (des chaines a la mode c)

si je fais (adresse en dur)

curl_easy_setop (curl, CURLOPT_URL,
"http://monadresse:80/?action=PING");

c'est ok

mais si je passe par un osstringstream url pour construire l'adresse,
puis

url.str().c_str() en parametre j'ai une ereur a l'execution?

<url> mailformed

merci

10 réponses

1 2
Avatar
Fabien LE LEZ
On Wed, 28 Jan 2009 15:14:28 +0100, (Bruno Causse):

la plupart (et notament curl_easy_setopt) reclament des char* c



La fonction c_str() renvoie un "char const*", pas un "char*".
On ne peut donc pas l'utiliser directement.

Tu as une fonction censée être appelée depuis du code C, et pas
vraiment compatible avec C++. Tu dois donc l'encapsuler.
(En passant, vérifie si ça n'est pas déjà fait -- il existe peut-être
une bibliothèque d'interfaçage de tes fonctions C avec le C++.)

La méthode canonique pour créer un "char*" est d'utiliser
std::vector<char> :

void CurlEasySetop (UnType curl, UnAutreType x, std::string const&
url)
{
std::vector<char> buf (url.begin(), url.end());
buf.push_back ('');
curl_easy_setop (curl, x, &buf[0]);
}

Vérifie tout de même que tu n'as pas besoin d'un buffer plus grand.
Par exemple, si ta fonction C s'attend à recevoir un buffer de 256
octets, tu peux écrire :

void CurlEasySetop (UnType curl, UnAutreType x, std::string const&
url)
{
std::vector<char> buf (url.begin(), url.end());
buf.push_back ('');
buf.resize (256);
curl_easy_setop (curl, x, &buf[0]);
}


Si, dans la doc de la bibliothèque en question, il est écrit
explicitement qu'en aucun cas, la fonction ne pourra modifier le
contenu du buffer, l'usage de "char*" est une erreur -- la fonction
aurait dû réclamer un "char const*" (mais peut-être que ça n'existe
tout simplement pas en C ?)

Dans ce cas, il faut indiquer au compilo que le prototype est erroné :

void CurlEasySetop (UnType curl, UnAutreType x, char const* url)
{
curl_easy_setop (curl, x, const_cast<char*>(url));
}

void CurlEasySetop (UnType curl, UnAutreType x, std::string const&
url)
{
CurlEasySetop (curl, x, url.c_str());
}


<url> mailformed



Non.
Avatar
Mickaël Wolff
Bruno Causse a écrit :
mais si je passe par un osstringstream url pour construire l'adresse,
puis

url.str().c_str() en parametre j'ai une ereur a l'execution?



Qu'affiche la ligne suivante après avoir rempli l'URL ?

std::cout << url.str().c_str() << std::endl ;

--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org

Seeking for a position <http://lupusmic.org/pro/>
Avatar
pjb
(Bruno Causse) writes:

bonjour,

je tente d'utiliser CURL.

la plupart (et notament curl_easy_setopt) reclament des char* c
(terminés par ) en parametre (des chaines a la mode c)

si je fais (adresse en dur)

curl_easy_setop (curl, CURLOPT_URL,
"http://monadresse:80/?action=PING");

c'est ok

mais si je passe par un osstringstream url pour construire l'adresse,
puis

url.str().c_str() en parametre j'ai une ereur a l'execution?

<url> mailformed



Probablement parce que l'url est malformé. Mais comme tu ne produit
aucun code à tester, on ne peut rien dire... En tout cas, chez moi ça
marche:


extern "C"{
#include <assert.h>
#include <string.h>
}
#include <sstream>
#include <iostream>

using namespace std;

int main()
{
ostringstream url;
url<<"http";
url<<"://";
url<<"monadresse";
url<<":";
url<<80;
url<<"/";
url<<"?";
url<<"action"<<"="<<"PING";

assert(url.str()=="http://monadresse:80/?action=PING");
assert(::strcmp(url.str().c_str(),"http://monadresse:80/?action=PING")==0);

cout<<"string "<<url.str()<<endl;
cout<<"char* "<<url.str().c_str()<<endl;

return(0);
}

/*
-*- mode: compilation; default-directory: "~/src/tests-c++/" -*-
Compilation started at Wed Jan 28 16:04:49

SRC="/home/pjb/src/tests-c++/str.c++" ; EXE="str" ; g++ -I$HOME/opt/libanevia-1.0.0-manager2-trunk-debug/include/libanevia-1.0/ -L$HOME/opt/libanevia-1.0.0-manager2-trunk-debug/lib/ -lanevia -g3 -ggdb3 -o ${EXE} ${SRC} && ./${EXE} && echo status = $?
string http://monadresse:80/?action=PING
char* http://monadresse:80/?action=PING
status = 0

Compilation finished at Wed Jan 28 16:04:50

*/
--
__Pascal Bourguignon__
Avatar
pasdespam
Pascal J. Bourguignon wrote:

(Bruno Causse) writes:

> bonjour,
>
> je tente d'utiliser CURL.
>
> la plupart (et notament curl_easy_setopt) reclament des char* c
> (terminés par ) en parametre (des chaines a la mode c)
>
> si je fais (adresse en dur)
>
> curl_easy_setop (curl, CURLOPT_URL,
> "http://monadresse:80/?action=PING");
>
> c'est ok
>
> mais si je passe par un osstringstream url pour construire l'adresse,
> puis
>
> url.str().c_str() en parametre j'ai une ereur a l'execution?
>
> <url> mailformed

Probablement parce que l'url est malformé. Mais comme tu ne produit
aucun code à tester, on ne peut rien dire... En tout cas, chez moi ça
marche:



non, mon adresse est correcte.

la soluce m'a ete fournie par fabien

avec une nouvelle decouverte :-)

std::vector < char> ( url.str().begin(), url.str().end());
ne fonctionne pas (2 chaines?)

mais

const std::string& sURL = url.str();
std::vector < char> ( sURL.begin(), sURL.end());
c'est ok

merci a tous
Avatar
Fabien LE LEZ
On Wed, 28 Jan 2009 16:29:16 +0100, (Bruno Causse):

std::vector < char> ( url.str().begin(), url.str().end());



Ça n'a rien à voir avec le code que je t'ai indiqué.
Avatar
Michel Decima
Bruno Causse a écrit :

avec une nouvelle decouverte :-)

std::vector < char> ( url.str().begin(), url.str().end());
ne fonctionne pas (2 chaines?)



Oui, deux chaines distinctes, parce que str() retourne une valeur,
pas une reference.

const std::string& sURL = url.str();
std::vector < char> ( sURL.begin(), sURL.end());
c'est ok



mais il ne vaut pas oublier d'ajouter le '' final.
Avatar
PasDeSpam
Fabien LE LEZ wrote:

Ça n'a rien à voir avec le code que je t'ai indiqué.



je n'ai rien dit de tel.
Avatar
James Kanze
On Jan 28, 3:35 pm, Fabien LE LEZ wrote:
On Wed, 28 Jan 2009 15:14:28 +0100, (Bruno Causse):



>la plupart (et notament curl_easy_setopt) reclament des char* c



La fonction c_str() renvoie un "char const*", pas un "char*".
On ne peut donc pas l'utiliser directement.



Tu as une fonction censée être appelée depuis du code C, et pas
vraiment compatible avec C++. Tu dois donc l'encapsuler.
(En passant, vérifie si ça n'est pas déjà fait -- il existe peut- être
une bibliothèque d'interfaçage de tes fonctions C avec le C++.)



La méthode canonique pour créer un "char*" est d'utiliser
std::vector<char> :



Pas vraiment. Ça dépend de l'utilisation du char* dans la
fonction. Beaucoup de fonctions C ne sont pas « const
correct » ; elle prend un char* sans modifier la chaîne. Dans
ce cas-là, la méthode canonique, c'est un const_cast sur le
resultat d'un appel à string::c_str().

Du fait que ça marche quand il passe une chaîne constante,
j'imagine que c'est le cas ici. Le vector<char> n'est nécessaire
que dans le cas où la fonction veut modifier (c-à-d qu'on passe
un buffer, plutôt qu'une chaîne).

[...[
Si, dans la doc de la bibliothèque en question, il est écrit
explicitement qu'en aucun cas, la fonction ne pourra modifier
le contenu du buffer, l'usage de "char*" est une erreur -- la
fonction aurait dû réclamer un "char const*" (mais peut-être
que ça n'existe tout simplement pas en C ?)



Ça existe, mais son utilisation n'est pas aussi répandue qu'en
C++. Si certaines bibliothèques (la bibliothèque standard du
langage, Posix, etc.) s'appliquent à l'utiliser de façon
systèmatique, d'autres l'ignore complètement.

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Avatar
James Kanze
On Jan 28, 4:29 pm, (Bruno Causse) wrote:
Pascal J. Bourguignon wrote:



> (Bruno Causse) writes:



> > je tente d'utiliser CURL.



> > la plupart (et notament curl_easy_setopt) reclament des
> > char* c (terminés par ) en parametre (des chaines a la
> > mode c)



> > si je fais (adresse en dur)



> > curl_easy_setop (curl, CURLOPT_URL,
> > "http://monadresse:80/?action=PING");



> > c'est ok



> > mais si je passe par un osstringstream url pour construire
> > l'adresse, puis



> > url.str().c_str() en parametre j'ai une ereur a l'execution?



> > <url> mailformed



> Probablement parce que l'url est malformé. Mais comme tu ne
> produit aucun code à tester, on ne peut rien dire... En
> tout cas, chez moi ça marche:



non, mon adresse est correcte.



la soluce m'a ete fournie par fabien



avec une nouvelle decouverte :-)



std::vector < char> ( url.str().begin(), url.str().end());
ne fonctionne pas (2 chaines?)



Tout à fait.

mais



const std::string& sURL = url.str();



Pourquoi la référence ici ?

std::vector < char> ( sURL.begin(), sURL.end());
c'est ok



Il serait quand même intéressant de voir ton code d'origine. A
priori, je taperais sur un problème de durée de vie d'un
temporaire quelque part. Si tu appelles directement :

std::ostringstream s ;
// ...
someFunction( s.str().c_str() ) ;

ça doit marcher. (J'en fait autant assez souvent, sans
problèmes.) En revanche, la chaîne renvoyée par s.str() est bien
un temporaire (une copie de la chaîne dans le stream), dont la
durée de vie termine à la fin de l'expression complète qui le
contient. Je ne crois pas trop à ce que le vector soit
nécessaire en soit, mais c'est une variable, avec une durée de
vie plus longue qu'un temporaire, et ça peut faire une
différence importante.

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Avatar
Fabien LE LEZ
On Thu, 29 Jan 2009 00:11:13 -0800 (PST), James Kanze
:

Beaucoup de fonctions C ne sont pas « const
correct » ; elle prend un char* sans modifier la chaîne.



Yep, c'est bien ce que je dis plus bas :

Si, dans la doc de la bibliothèque en question, il est écrit
explicitement qu'en aucun cas, la fonction ne pourra modifier
le contenu du buffer, l'usage de "char*" est une erreur -- la
fonction aurait dû réclamer un "char const*"





Faut bien lire la doc. Par exemple, la fonction CreateProcess de
l'API Win32 est tordue : on passe la ligne de commande sous forme
d'une chaîne constante... sauf si on compile en Unicode.

"The Unicode version of this function, CreateProcessW, can modify the
contents of this string. Therefore, this parameter cannot be a pointer
to read-only memory (such as a const variable or a literal string). If
this parameter is a constant string, the function may cause an access
violation."
http://msdn.microsoft.com/en-us/library/ms682425.aspx
1 2