Newsgroup: it.comp.lang.c++
Titolo: eccezione all'assegnazione di std::string

Ho un array di std::string, codice:
 
typedef std::string ROSTER[7];
std::string Line;
 
// etc. etc...
 
ROSTER R;
 
for (int i = 0; i < 7; i++)
	{
 
	// etc. etc...
 
	ROSTER[i] = Line; // kaboom!
			  // accesso a indirizzo 0x00000000
 
	};
 
Preciso che "Line" è sempre di pochi caratteri e non contiene roba 
strana (eliminata prima). Inizialmente dava l'eccezione sempre alla 
prima assegnazione, poi provando con un txtfile diverso lo faceva alla 
terza.
 
Com'è possibile? Mi è venuto in mente che forse è un problema di 
impaccamento, nel senso che siccome sono in un array, le string devono 
essere lunghe al max N bytes e non di più... ma mi pare incredibile :-|
 

      ROSTER[i] = Line; // kaboom!
 
tanto per iniziare volevi scrivere:
R[i] = Line;
vero?


Sì, ho sbagliato a scrivere nel post.
 
Doveva essere R[i] = Line;
 
 

 Doveva essere R[i] = Line;
 
Ok, per il resto non vedo nessun errore.
Il problema dovrebbe essere altrove, dove magari la memoria viene 
corrotta, per darti poi infine il segfault a quella assegnazione.
Dovresti ridurre il tuo codice al minimo indispensabile necessario per 
replicare il problema e quindi postarlo. Ciao.


 
 
-- 
1) Resistere, resistere, resistere.
2) Se tutti pagano le tasse, le tasse le pagano tutti
Soviet_Mario - (aka Gatto_Vizzato)
 

 valore valido dovrebbe essere inizializzata con un array fisico ?
 
Eh ?!?

 essere lunghe al max N bytes e non di piů... ma mi pare incredibile :-|
 
No. Questo puoi ampiamente escluderlo. L'implementazione di std::string
non e' banale e c'e' dentro un po' di maggico, ma e' perfettamente in
grado di gestire questo caso. 
 
Ora, un po' di suggerimenti: 
 
1. guarda in faccia le stringhe che ti fanno esplodere
2. prova con qualche implementazione diversa della stdlib. Facile che
l'implementazione sotto delle stringhe sia molto diversa (ricordo una
comparazione fra comeau, ms, gcc etc).
3. provato codice "robusto" per avere strongly exception safety:
 
std::string(string1).swap(string2);
 
L'errore che da cosa e'? length_error?
 
 
 
 
-- 
-riko
http://www.enrico-franchi.org/
 
http://rik0-techtemple.blogspot.com/
 

 2. prova con qualche implementazione diversa della stdlib.
 
Cioè prendere un diverso set di header per la stl? Ma si può fare? Non è 
che poi il compilatore si incavola? O_O
 

 che poi il compilatore si incavola? O_O
 
Dipende. Di per se tu puoi non linkare e non usare gli headers della
libreria del tuo compilatore. Tempo fa era ben piu' comune di oggi.
Anzi, la STL non era nemmeno standard, una volta. ;)
 
Puoi anche cambiare compilatore... ma si, in generale "si puo' fare",
nello specifico bisogna vedere.


 Ma perché fa ciň?
 
Perche' c'e' qualche errore nel programma :) magari dove generi/leggi 
(non si sa dove/come perche' non lo hai scritto) il testo che poi 
assegni alle std:string.
Se puoi postare un po' piu' di codice, ovviamente lo si trova. Ciao.

 Eh ?!?
 
Credo che stia dicendo che il suo dubbio e' che R non sia di tipo array,
bensi' di tipo puntatore a stringa.



Ecco la routine incriminata, con le due routinine di supporto allegate 
sotto. Ho tolto un pò di codice ininfluente.
L'eccezione viene lanciata su uno degli assegnamenti nello switch() 
appena prova ad assegnare una stringa che era + corta di quella del 
ciclo precedente...
//-------------------------------------------
 
typedef std::string STroster[7];
ifstream InFile; // già aperto altrove su un file PGN
		 // (partite di scacchi)
 
bool CheckTagRoster(STroster *R)
{
std::string Line, Label;
getline(InFile, Line);
 
// esempi di tag:
// [<keyword> "<stringa dati>"]
// [Event "nome del torneo"]
// [Site "luogo di svolgimento del torneo"]
// [Date "2009.01.03"]
// ecc. ecc.
 
while (Line.length() != 0)
     {
     if (Line[0]=='[')              // c'è un tag da analizzare
         {
         Label = tagsplitter(&Line);
		// lo divide in nome e valore.
		// Line viene riassegnata con il valore del tag
         if ((Label.length()!=0)&&(Line.length()!=0))
             {
             switch (TagKind(Label))	// classifica il tag in base alla 
keyword
                 {
                 case 0 : { *R[0] = Line;
                     };
                     break;
                 case 1 : { *R[1] = Line;
                     };
                     break;
                 case 2 : { *R[2] = Line;
                     };
                     break;
                 case 3 : { *R[3] = Line;
                     };
                     break;
                 case 4 : { *R[4] = Line;
                     };
                     break;
                 case 5 : { *R[5] = Line;
                     };
                     break;
                 case 6 : { *R[6] = Line;
                     };
                     break;
                 default : {
                     }
                 };
 
             getline(InFile,Line);
             if (InFile.eof())
                 return false;
             }
         else        // non è un tag valido
             {
             return false;
             };
         }
     else    //  non è un tag
         {
         if (Line[0]=='%')   //  se è un commento saltiamolo
             {
             getline(InFile, Line);
             if (InFile.eof())
                 return false;
             }
         else                //  sennò diamo errore
             {
             return false;
             };
         };
     };
 
return STrosterOK(R); // testa il roster generato e vede se è valido
}
 
//----------------------------------------
std::string tagsplitter(std::string *V)
{
std::string L;
int i = V->find(' ');
L = V->substr(1, i-1);
*V = V->substr(i + 2, V->length() - 2);
return L;
};
 
//----------------------------------------
int TagKind(std::string LT)
{
for (int i = 0; i < 7; i++)
     {
     if (LT == STrosterTokens[i])
         return i;
     };
 
return SOMEOTHERTAG;
};

 ciclo precedente...
 
L'errore e' evidente :)
 
====================================================
 
Quando passi un array come argomento a una funzione, basta che passi il 
nome dell'array, che e' gia' il puntatore al primo elemento.
 
Ossia dovevi fare:
 
bool CheckTagRoster(STroster R)
{
   <CUT>
}
e all'interno della funzione usare:
R[0] = Line;
 
e quando chiami la funzione fare
CheckTagRoster(R)
 
====================================================
 
Se invece vuoi lasciare le cose come sono (ma te lo sconsiglio)
basta solo che trasformi per esempio:
*R[0] = Line;
in
(*R)[0] = Line;
 
====================================================
 
Tutto qui. Ciao.
 
 
 
 

 bensi' di tipo puntatore a stringa.
 
- sei sicuro che R sia fisicamente un array
- non solo una singola variabile il cui tipo è interpretato come array
- per avere un valore valido dovrebbe essere inizializzata con un array 
fisico
 
mi pare estremamente piu' oscuro :)


 
ah, provvedo

 ah, provvedo
 
Giusto per completezza dell'informazione, aggiungo che c'e' ovviamente 
un caso (ed e' un "classico" per i programmatori C) in cui si passa alla 
funzione l'indirizzo del puntatore al primo elemento dell'array: e' 
quando si vuole allocare l'array all'interno della funzione.
In questo casi si DEVE passare l'indirizzo del puntatore al primo
elemento. Allego esempio. Ciao.
 
===========================================
#include <stdio.h>
#include <stdlib.h>
 
void creaArray(char **s)
{
     *s = (char *)malloc(3);
     (*s)[0] = 'O';
     (*s)[1] = 'K';
     (*s)[2] = '\0';
}
 
int main()
{
     char *s;
     creaArray(&s);
     printf("s: %s\n", s);
 
     return 0;
}
===========================================
 
P.S.
Anche qui nell'assegnazione, se non avessi messo le parentesi come avevi 
fatto tu,  avrei avuto il "segmentation fault".
QUESTO E' SBAGLIATO:
*s[0] = 'O';
*s[1] = 'K';
*s[2] = '\0';

 mi pare estremamente piu' oscuro :)
 
Io stavo solo interpretando la domanda di Soviet. ;)
