[aCC] istream_iterator et vector::assign avec HP-UX aCC

Le
Michel Decima
Bonjour,

J'ai un comportement anormal avec le programme dont le code est
ci-dessous sur HP-UX/IA64 avec le compilateur aCC : a l'execution,
le programme plante avec un segfault sur l'affichage du premier
element du tableau.

J'ai testé ce code avec g++-4.1.2 sous Linux et xlC-6.0 sur AIX,
il me donne bien le resultat attendu Est-ce que j'ai raté
quelque-chose dans le code, ou bien il s'agit d'un probleme du
compilateur et/ou la bibliotheque standard sur HPUX ?

//--
#include <iostream>
#include <sstream>
#include <iterator>
#include <vector>
#include <string>

int main()
{
std::string text = "a b c d";
std::vector< std::string > v;

std::istringstream input( text );
v.assign( std::istream_iterator< std::string >( input ),
std::istream_iterator< std::string >() );

if ( !v.empty() ) {
std::cout << v[ 0 ] << std::endl; // boum.
}
}
//--

J'ai essayé des variantes avec std::ifstream, std::list, d'autres
iterateurs, bref, tout fonctionne correctement. Il semble que le
probleme ne se produit que sur l'utilisation de la fonction membre
assign de std::vector<string> avec des istream_iterator

D'apres le debugger, l'erreur proviendrait de la:

Program terminated with signal 11, Segmentation fault.
SEGV_MAPERR - Address not mapped to object
#0 0x400f5a0:1 in main () at /opt/aCC/include_std/string:406
406 return _C_pref()->__nchars_;

Program terminated with signal 11, Segmentation fault.
SEGV_MAPERR - Address not mapped to object
#0 0x4012a80:1 in std::basic_ostream<char,std::char_traits<char> >&
std::operator<<<char,std::char_traits<char>,std::allocator<char> > ()
at /opt/aCC/include_std/string:406
406 return _C_pref()->__nchars_;


La ligne 406 du fichier /opt/aCC/include_std/string correspond a
la fonction membre std::string::size() :

size_type size () const {
return _C_pref()->__nchars_; // ligne 406
}


Le detail des versions de l'OS et du compilateur:

# uname -a
HP-UX hq1e01v7 B.11.23 U ia64 3373079756 unlimited-user license
# aCC -V
aCC: HP C/aC++ B3910B A.06.14 [Feb 22 2007]

Si quelqu'un dans l'assemblée pouvait tester ce code sur une plateforme
similaire, ca m'aiderait beaucoup

Merci.

--
MD.
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
Michael DOUBEZ
Le #312675
Bonjour,

J'ai un comportement anormal avec le programme dont le code est
ci-dessous sur HP-UX/IA64 avec le compilateur aCC : a l'execution,
le programme plante avec un segfault sur l'affichage du premier
element du tableau.

J'ai testé ce code avec g++-4.1.2 sous Linux et xlC-6.0 sur AIX,
il me donne bien le resultat attendu... Est-ce que j'ai raté
quelque-chose dans le code, ou bien il s'agit d'un probleme du
compilateur et/ou la bibliotheque standard sur HPUX ?

//--------------------------------------------------------------
#include <iostream>
#include <sstream>
#include <iterator>
#include <vector>
#include <string>

int main()
{
std::string text = "a b c d";
std::vector< std::string > v;

std::istringstream input( text );
v.assign( std::istream_iterator< std::string >( input ),
std::istream_iterator< std::string >() );


Je ne vois pas de raison pour que ça plante. Peut être un bug de la stl.

Et avec un back_inserter (puique de toutes façons le vector est vide)?

std::copy(std::istream_iterator< std::string >( input ),
std::istream_iterator< std::string >(),
std::back_inserter(v) );



if ( !v.empty() ) {
std::cout << v[ 0 ] << std::endl; // boum.
}
}


Michael

James Kanze
Le #312674
Michel Decima wrote:

J'ai un comportement anormal avec le programme dont le code est
ci-dessous sur HP-UX/IA64 avec le compilateur aCC : à l'execution,
le programme plante avec un segfault sur l'affichage du premier
element du tableau.

J'ai testé ce code avec g++-4.1.2 sous Linux et xlC-6.0 sur AIX,
il me donne bien le resultat attendu... Est-ce que j'ai raté
quelque-chose dans le code, ou bien il s'agit d'un probleme du
compilateur et/ou la bibliotheque standard sur HPUX ?

//--------------------------------------------------------------
#include <iostream>
#include <sstream>
#include <iterator>
#include <vector>
#include <string>

int main()
{
std::string text = "a b c d";
std::vector< std::string > v;

std::istringstream input( text );
v.assign( std::istream_iterator< std::string >( input ),
std::istream_iterator< std::string >() );

if ( !v.empty() ) {
std::cout << v[ 0 ] << std::endl; // boum.
}
}
//--------------------------------------------------------------


Le code m'a l'air bon. Il fonctionne aussi, avec tous les
compilateurs auxquels j'ai accès (g++, Sun CC avec le STLport,
VC++). Y compris dans des modes vérificatrices.

J'ai essayé des variantes avec std::ifstream, std::list, d'autres
iterateurs, bref, tout fonctionne correctement. Il semble que le
probleme ne se produit que sur l'utilisation de la fonction membre
assign de std::vector<string> avec des istream_iterator...

D'apres le debugger, l'erreur proviendrait de la:

Program terminated with signal 11, Segmentation fault.
SEGV_MAPERR - Address not mapped to object
#0 0x400f5a0:1 in main () at /opt/aCC/include_std/string:406
406 return _C_pref()->__nchars_;

Program terminated with signal 11, Segmentation fault.
SEGV_MAPERR - Address not mapped to object
#0 0x4012a80:1 in std::basic_ostream<char,std::char_traits<char> >&
std::operator<<<char,std::char_traits<char>,std::allocator<char> > ()
at /opt/aCC/include_std/string:406
406 return _C_pref()->__nchars_;

La ligne 406 du fichier /opt/aCC/include_std/string correspond a
la fonction membre std::string::size() :

size_type size () const {
return _C_pref()->__nchars_; // ligne 406
}


Ce qui ne veut rien dire. A priori, le vrai problème, c'est en
amont. Ce qui fait qu'arrivé ici, il y a un pointeur qui foire.

Le detail des versions de l'OS et du compilateur:

# uname -a
HP-UX hq1e01v7 B.11.23 U ia64 3373079756 unlimited-user license
# aCC -V
aCC: HP C/aC++ B3910B A.06.14 [Feb 22 2007]

Si quelqu'un dans l'assemblée pouvait tester ce code sur une
plateforme similaire, ca m'aiderait beaucoup...


La vrai question, c'est d'où provient l'implémentation de la
bibliothèque. Est-ce que c'est propre à HP, ou est-ce que c'est
une des implémentations classiques (Dinkumware, STLport, Rogue
Wave, etc.) ? De toute façon, ça a tout à fait l'air d'être une
erreur dans la bibliothèque.

--
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

Michel Decima
Le #312673

std::istringstream input( text );
v.assign( std::istream_iterator< std::string >( input ),
std::istream_iterator< std::string >() );


Je ne vois pas de raison pour que ça plante. Peut être un bug de la stl.


Merci pour la confirmation.

Et avec un back_inserter (puique de toutes façons le vector est vide)?

std::copy(std::istream_iterator< std::string >( input ),
std::istream_iterator< std::string >(),
std::back_inserter(v) );


Voyant que ca plantait, j'ai essayé cette solution avec copy et
back_inserter, et ca passe sans probleme.

J'ai aussi essayé le constructeur de vector qui prends deux
iterateurs:

std::istringstream input( text );
std::vector< std::string >
x( (std::istream_iterator< std::string >( input )),
std::istream_iterator< std::string >() );

ansi qu'une list a la place du vector:

std::list< std::string > x;
std::istringstream input( text );
x.assign( std::istream_iterator< std::string >( input ),
std::istream_iterator< std::string >() );

les deux fonctionne correctement.

Bref, on dirait bien que c'est un probleme de la bibliotheque.


Michel Decima
Le #312671
Le code m'a l'air bon. Il fonctionne aussi, avec tous les
compilateurs auxquels j'ai accès (g++, Sun CC avec le STLport,
VC++). Y compris dans des modes vérificatrices.


Merci aussi pour la verification de confirmité du code. Il est
pourtant tout simple, mais des fois on passe a coté d'une betise
evidente...

La ligne 406 du fichier /opt/aCC/include_std/string correspond a
la fonction membre std::string::size() :

size_type size () const {
return _C_pref()->__nchars_; // ligne 406
}


Ce qui ne veut rien dire. A priori, le vrai problème, c'est en
amont. Ce qui fait qu'arrivé ici, il y a un pointeur qui foire.


Oui, ca veut bien dire qu'une string est corrompue, mais ca ne
dit pas ou s'est produit le probleme.


Le detail des versions de l'OS et du compilateur:

# uname -a
HP-UX hq1e01v7 B.11.23 U ia64 3373079756 unlimited-user license
# aCC -V
aCC: HP C/aC++ B3910B A.06.14 [Feb 22 2007]


La vrai question, c'est d'où provient l'implémentation de la
bibliothèque. Est-ce que c'est propre à HP, ou est-ce que c'est
une des implémentations classiques (Dinkumware, STLport, Rogue
Wave, etc.) ? De toute façon, ça a tout à fait l'air d'être une
erreur dans la bibliothèque.


Il s'agit de l'implementation RogueWave, mais j'ai du mal a trouver
la version.

Dans le code précédent, j'ai remplacé std::string par une pseudo classe
String minimale, et maintenant ca ne plante plus a l'affichage, mais
le contenu de la premiere chaine du vecteur est surprenant (le reste
aussi d'ailleurs):

struct String {
char str[100];
String( char const* s = "default" ) { strcpy( str, s); }
String( String const& other )
{ strcpy( str, other.str); }
String& operator=(String const& other )
{ strcpy( str, other.str); return *this; }
};

std::istream& operator>>( std::istream& src, String& dest )
{
src.width( 99 );
src >> dest.str;
return src;
}

std::ostream& operator<< ( std::ostream& dest, String const& src )
{
dest << src.str;
return dest;

}

int main()
{
std::string text = "a b c d";

std::vector< String > x;
x.push_back( String( "toto" ) );
std::istringstream input( text );
x.assign( std::istream_iterator< String >( input ),
std::istream_iterator< String >() );
std::cout << "size=" << x.size() << std::endl;
for ( unsigned int i=0; i < x.size(); ++i ) {
std::cout << "x[ " << i << " ]=" << x[ i ] << std::endl;
}
}

En sortie, ca donne ca:

size=4
x[ 0 ]=toto
x[ 1 ] x[ 2 ] x[ 3 ]
La taille du vecteur correspond bien a ce qui est attendu, mais
le premier element du vecteur n'a pas été remplacé, et les autres
contiennent une chaine vide...

Si je remplace l'appel a vector::assign() par erase + insert

x.erase( x.begin(), x.end() );
x.insert( x.begin(),
std::istream_iterator< String >( input ),
std::istream_iterator< String >() );

J'obtiens bien le resultat attendu, c'est a dire:

size=4
x[ 0 ]=a
x[ 1 ]=b
x[ 2 ]=c
x[ 3 ]=d

J'ai regardé la definition de vector::assign(), et c'est à premiere
vue equivalent a la combinaison erase + insert, donc je devrais avoir
le meme resultat dans les deux cas...

Bref, je n'y comprends pas grand chose, sauf que je vais devoir
contacter le support HP.

Merci pour votre aide.
MD.


Publicité
Poster une réponse
Anonyme