Torna indietro   Hardware Upgrade Forum > Software > Programmazione

Sony WF-1000X M6: le cuffie in-ear di riferimento migliorano ancora
Sony WF-1000X M6: le cuffie in-ear di riferimento migliorano ancora
WF-1000X M6 è la sesta generazione di auricolare in-ear sviluppata da Sony, un prodotto che punta a coniugare facilità di utilizzo con una elevata qualità di riproduzione dei contenuti audio e una cura nella riduzione del rumore ambientale che sia da riferimento
Snowflake porta l'IA dove sono i dati, anche grazie a un accordo con OpenAI
Snowflake porta l'IA dove sono i dati, anche grazie a un accordo con OpenAI
Snowflake ha presentato diverse novità per la sua piattaforma legate all'intelligenza artificiale. Quella forse più eclatante è una collaborazione con OpenAI, ma non mancano diverse nuove funzionalità che rendono la piattaforma più flessibile e in grado di rispondere meglio alle esigenze in continuo cambiamento delle aziende
Sistema Mesh Roamii BE Pro: il Wi-Fi 7 secondo MSI
Sistema Mesh Roamii BE Pro: il Wi-Fi 7 secondo MSI
Con velocità teoriche fino a 11 Gbps, gestione tramite app intelligente e protezione avanzata dei dispositivi, Roamii BE Pro porta il Wi‑Fi 7 tri‑band nelle abitazioni più esigenti. Un sistema Wi-Fi Mesh proposto da MSI allo scopo di garantire agli utenti una rete fluida e continua capace di sostenere streaming 8K, gaming competitivo e le applicazioni moderne più esigenti in termini di banda
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 24-07-2010, 22:46   #1
Opcode
Member
 
L'Avatar di Opcode
 
Iscritto dal: Jun 2010
Città: Asti
Messaggi: 85
[c++] problema con std::string che risulta illeggibile

Sera a tutti, ho un problema piuttosto strano in un metodo che ho scritto.
Il problema è che la stringa (restituita tramite il metodo c_str() come const char), risulta in un insieme di caratteri illeggibili.
Ma prima di andare avanti ecco la definizione del metodo:
Codice:
const char *Resources::getImage(const char *resourceID) {
	TiXmlNode *imagesNode = this->resourceFile.FirstChild("Images");
	TiXmlElement *resourceImage;

	for (resourceImage = imagesNode->FirstChildElement("Image");
		 resourceImage != NULL;
		 resourceImage = imagesNode->NextSiblingElement())
	{

		if (strcmp(resourceImage->Attribute("identifier"), resourceID) == 0) {
			if(resourceImage->Attribute("path")) {
                                // DA QUI LA STRINGA ILLEGGIBILE, resourcePath
				std::string resourcePath;
				resourcePath.append(this->resourcesRoot);
				resourcePath.append(std::string(resourceImage->Attribute("path")));

				return resourcePath.c_str();
			}
			else {
				std::string errorMessage("Missing reference for: ");
				errorMessage.append(resourceID);

				Engine::instance()->fatalError(errorMessage.c_str());
			}
		} 
		else {
			std::string alertMessage("Cannot get the resource reference to: ");
			alertMessage.append(resourceID);

			Engine::instance()->fatalError(alertMessage.c_str());
		}
	}
	return NULL;
}
Come si può intuire, questo metodo dovrebbe cercare in un file xml (gestito attraverso la libreria TinyXML.
Il problema è rappresentato da resourcePath che è una stringa assemblata con this->resourcesRoot che è una stringa contenente una porzione di path, e il contenuto dell'attributo "path" dell'elemento, che viene restituito sotto forma di const char *.

Se provo a stampare (per debug) da dentro la funzione, o a restituire il singolo this->resourcesRoot o resourceImage->Attribute("path") questi sono perfettamente leggibili e funzionanti, ma in questo punto:
Codice:
                                // DA QUI LA STRINGA ILLEGGIBILE, resourcePath
				std::string resourcePath;
				resourcePath.append(this->resourcesRoot);
				resourcePath.append(std::string(resourceImage->Attribute("path")));

				return resourcePath.c_str();
Si verifica il mistero, per completezza inserisco una immagine che mostra a schermo il risultato ottenuto (la scritta dopo è una informazione di debug, non ha alcuna attinenza con il metodo in questione):


Ringrazio in anticipo chiunque si interessi.
Opcode è offline   Rispondi citando il messaggio o parte di esso
Old 25-07-2010, 01:00   #2
Albi89
Senior Member
 
Iscritto dal: May 2004
Città: Napoli
Messaggi: 773
Quote:
Originariamente inviato da Opcode Guarda i messaggi
...
Il puntatore che ritorni col metodo c_str() è invalidato nel momento in cui la stringa viene deallocata (cioè all'atto del return).

Se non hai la possibilità di ritornare una std::string, puoi allocare dinamicamente una stringa C, copiarvi il contenuto della tua std::string usando strcpy e il metodo c_str() e dunque ritornare un puntatore a questa.
__________________
If builders built buildings the way programmers wrote programs, then the first woodpecker that came along would destroy civilization.
--Gerald Weinberg
Albi89 è offline   Rispondi citando il messaggio o parte di esso
Old 25-07-2010, 11:50   #3
Opcode
Member
 
L'Avatar di Opcode
 
Iscritto dal: Jun 2010
Città: Asti
Messaggi: 85
Quote:
Originariamente inviato da Albi89 Guarda i messaggi
Il puntatore che ritorni col metodo c_str() è invalidato nel momento in cui la stringa viene deallocata (cioè all'atto del return).

Se non hai la possibilità di ritornare una std::string, puoi allocare dinamicamente una stringa C, copiarvi il contenuto della tua std::string usando strcpy e il metodo c_str() e dunque ritornare un puntatore a questa.
Caspita che problema tedioso +
Purtroppo non ho possibilità di restituire direttamente una stringa in quanto il risultato è utilizzato come parametro per altre funzioni C, comunque la soluzione che mi hai proposto ha funzionato alla grande

Mi ero dimenticato dello scope della variabile, e sinceramente, pensavo che il risultato di c_str() fosse permanente, non dipendente dalla classe.

Grazie mille, mi hai risparmiato un'altra giornata di grattacapi
Opcode è offline   Rispondi citando il messaggio o parte di esso
Old 25-07-2010, 13:18   #4
Albi89
Senior Member
 
Iscritto dal: May 2004
Città: Napoli
Messaggi: 773
Quote:
Originariamente inviato da Opcode Guarda i messaggi
Caspita che problema tedioso +
Purtroppo non ho possibilità di restituire direttamente una stringa in quanto il risultato è utilizzato come parametro per altre funzioni C, comunque la soluzione che mi hai proposto ha funzionato alla grande

Mi ero dimenticato dello scope della variabile, e sinceramente, pensavo che il risultato di c_str() fosse permanente, non dipendente dalla classe.

Grazie mille, mi hai risparmiato un'altra giornata di grattacapi
No, anzi, il puntatore restituito da c_str() è invalidato anche all'interno dello scope se la std::string viene modificata (almeno "da standard", se poi risulti ancora utilizzabile in alcuni casi non lo so, ma non bisogna farci affidamento).
Se è necessario riutilizzarne il contenuto, bisogna per forza copiarlo.
__________________
If builders built buildings the way programmers wrote programs, then the first woodpecker that came along would destroy civilization.
--Gerald Weinberg
Albi89 è offline   Rispondi citando il messaggio o parte di esso
Old 25-07-2010, 16:05   #5
tomminno
Senior Member
 
Iscritto dal: Oct 2005
Messaggi: 3306
Quote:
Originariamente inviato da Opcode Guarda i messaggi
Caspita che problema tedioso +
Purtroppo non ho possibilità di restituire direttamente una stringa in quanto il risultato è utilizzato come parametro per altre funzioni C, comunque la soluzione che mi hai proposto ha funzionato alla grande
Ricordati che poi devi deallocare l'array!
Se la utilizzi così hai un memory leak:
Codice:
Func(1,2,getImage("abc"));
sempre che Func non deallochi l'array, che è comunque molto pericoloso, perchè il giorno che devi chiamare:
Codice:
const char * img = getImage("abc");
Func(1,2,img);
Func2(3,4,img);
sei comunque fregato.

Chissà perchè il C++ venga sempre utilizzato come C con le classi...
tomminno è offline   Rispondi citando il messaggio o parte di esso
Old 25-07-2010, 16:13   #6
Albi89
Senior Member
 
Iscritto dal: May 2004
Città: Napoli
Messaggi: 773
Quote:
Originariamente inviato da tomminno Guarda i messaggi
Ricordati che poi devi deallocare l'array!
Se la utilizzi così hai un memory leak:
Codice:
Func(1,2,getImage("abc"));
sempre che Func non deallochi l'array, che è comunque molto pericoloso, perchè il giorno che devi chiamare:
Codice:
const char * img = getImage("abc");
Func(1,2,img);
Func2(3,4,img);
sei comunque fregato.

Chissà perchè il C++ venga sempre utilizzato come C con le classi...
Beh, tante volte la colpa non è dell'utente ma del dover far convivere più librerie, di cui magari alcune disponibili solo in C.

Ovviamente la necessità di deallocare esternamente c'è, non ne ho parlato perché incoraggio fortemente altre soluzioni (basti pensare che avere una allocazione nel tuo metodo, e una deallocazione a cura dell'utente del metodo, è rischiosissimo in ottica "black box" e renderebbe il tutto decisamente poco usabile da un ipotetico user della tua classe, senza considerare quanto si presti a tue distrazioni e leaks casalinghi).

Ti incoraggio fortemente a ritornare una std::string, e dunque a realizzare un wrapper per il tuo metodo che accetta solo char* (o, semplicemente, a passargliela tramite c_str(): in questo caso, e ammesso che tale metodo non debba modificare la stringa, sei sicuro della validità del puntatore per tutta la durata del metodo!).

Un'altra alternativa può essere ritornare una classe gestore della risorsa che incapsuli un char* e si occupi, oltre che di metterlo a disposizione del metodo chiamante, anche della sua deallocazione all'uscita dallo scope: sinceramente il gioco non vale la candela
__________________
If builders built buildings the way programmers wrote programs, then the first woodpecker that came along would destroy civilization.
--Gerald Weinberg
Albi89 è offline   Rispondi citando il messaggio o parte di esso
Old 25-07-2010, 16:13   #7
Opcode
Member
 
L'Avatar di Opcode
 
Iscritto dal: Jun 2010
Città: Asti
Messaggi: 85
Quote:
Originariamente inviato da Albi89 Guarda i messaggi
No, anzi, il puntatore restituito da c_str() è invalidato anche all'interno dello scope se la std::string viene modificata (almeno "da standard", se poi risulti ancora utilizzabile in alcuni casi non lo so, ma non bisogna farci affidamento).
Se è necessario riutilizzarne il contenuto, bisogna per forza copiarlo.
Capito, beh ti ringrazio della precisazione, mi sarà sicuramente utile per il futuro
Quote:
Originariamente inviato da tomminno Guarda i messaggi
Ricordati che poi devi deallocare l'array!
Ci avevo pensato, ma non ho trovato alcuna soluzione fruibile, poichè l'output viene dato in pasto alle funzioni di una libreria esterna, la maggior parte delle volte, infatti ci stavo proprio pensando, comunque stò implementando un sistema per vedere se la risorsa da caricare è già stata richiesta, e nel caso non fare nuovamente la trafila ma restituire direttamente path (una sorta di hash table per tenere traccia del risultato, in questo modo non ci sono dispersioni di memoria).
Quote:
Se la utilizzi così hai un memory leak:
Codice:
Func(1,2,getImage("abc"));
sempre che Func non deallochi l'array, che è comunque molto pericoloso, perchè il giorno che devi chiamare:
Codice:
const char * img = getImage("abc");
Func(1,2,img);
Func2(3,4,img);
sei comunque fregato.

Chissà perchè il C++ venga sempre utilizzato come C con le classi...
Hai qualche soluzione da consigliare?
Opcode è offline   Rispondi citando il messaggio o parte di esso
Old 25-07-2010, 16:18   #8
Albi89
Senior Member
 
Iscritto dal: May 2004
Città: Napoli
Messaggi: 773
Quote:
Originariamente inviato da Opcode Guarda i messaggi
Hai qualche soluzione da consigliare?
È importante capire se la libreria esterna deve o meno modificare la stringa che riceve... se nel prototipo vedi che è qualcosa del tipo:
Codice:
funzioneEsterna(const char* s);
il tuo metodo potrebbe tranquillamente ritornare una std::string, e passarla come:
Codice:
funzioneEsterna(mioMetodo().to_str());
__________________
If builders built buildings the way programmers wrote programs, then the first woodpecker that came along would destroy civilization.
--Gerald Weinberg
Albi89 è offline   Rispondi citando il messaggio o parte di esso
Old 25-07-2010, 16:25   #9
Opcode
Member
 
L'Avatar di Opcode
 
Iscritto dal: Jun 2010
Città: Asti
Messaggi: 85
Quote:
Originariamente inviato da Albi89 Guarda i messaggi
È importante capire se la libreria esterna deve o meno modificare la stringa che riceve... se nel prototipo vedi che è qualcosa del tipo:
Codice:
funzioneEsterna(const char* s);
il tuo metodo potrebbe tranquillamente ritornare una std::string, e passarla come:
Codice:
funzioneEsterna(mioMetodo().to_str());
Caspita, quello che mi fai notare non è affatto sbagliato.
Almeno per le funzioni che accettano il risultato di getImage, i prototipi sono tutti o quasi const char *filename, visto che devono solo occuparsi di caricare le risorse, non di modificare il nome.

Mi sà che agirò in questo modo.
Grazie ancora una volta
Opcode è offline   Rispondi citando il messaggio o parte di esso
Old 25-07-2010, 16:27   #10
Albi89
Senior Member
 
Iscritto dal: May 2004
Città: Napoli
Messaggi: 773
Quote:
Originariamente inviato da Opcode Guarda i messaggi
Caspita, quello che mi fai notare non è affatto sbagliato.
Almeno per le funzioni che accettano il risultato di getImage, i prototipi sono tutti o quasi const char *filename, visto che devono solo occuparsi di caricare le risorse, non di modificare il nome.

Mi sà che agirò in questo modo.
Grazie ancora una volta
Un'alternativa è mantenere il puntatore con uno scoped_array, ma mi sembra che l'altra soluzione sia più comoda
__________________
If builders built buildings the way programmers wrote programs, then the first woodpecker that came along would destroy civilization.
--Gerald Weinberg
Albi89 è offline   Rispondi citando il messaggio o parte di esso
Old 25-07-2010, 20:50   #11
Opcode
Member
 
L'Avatar di Opcode
 
Iscritto dal: Jun 2010
Città: Asti
Messaggi: 85
Quote:
Originariamente inviato da Albi89 Guarda i messaggi
Un'alternativa è mantenere il puntatore con uno scoped_array, ma mi sembra che l'altra soluzione sia più comoda
Ehm si decisamente più comoda la precendente
E poi adottare questa soluzione vorrebbe dire aggiungere un'altra libreria, ed essendo la precedente una soluzione funzionante, mi stà bene anche evitare di aggiungere altro

Comunque hai fatto benissimo a linkare la risorsa, molto utile
Ciao.
Opcode è offline   Rispondi citando il messaggio o parte di esso
Old 27-07-2010, 10:50   #12
cionci
Senior Member
 
L'Avatar di cionci
 
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
Quote:
Originariamente inviato da Opcode Guarda i messaggi
Caspita che problema tedioso +
Purtroppo non ho possibilità di restituire direttamente una stringa in quanto il risultato è utilizzato come parametro per altre funzioni C, comunque la soluzione che mi hai proposto ha funzionato alla grande
Sinceramente non mi piace molto allocare una risorsa dentro ad una funzione e poi dover imporre al chiamante la deallocazione.
Le soluzioni che ti posso proporre sono queste:

Codice:
std::string myFunction(...)
{
   std::string s;
   ...
   return s;
}
otherFunction(myFunction(...).c_str(), ...);
Codice:
char * myFunction(char * buffer, ...)
{
   std::string s;
   ...
   strncpy(buffer, s.c_str(), MAX_PATH);
   return buffer;
}

char buffer[MAX_PATH + 1];
otherFunction(myFunction(buffer, ...), ...);

Ultima modifica di cionci : 27-07-2010 alle 11:15.
cionci è offline   Rispondi citando il messaggio o parte di esso
Old 27-07-2010, 11:13   #13
DanieleC88
Senior Member
 
L'Avatar di DanieleC88
 
Iscritto dal: Jun 2002
Città: Dublin
Messaggi: 5989
Quote:
Originariamente inviato da cionci Guarda i messaggi
Codice:
std::string myFunction(char * buffer, ...)
{
   std::string s;
   ...
   strncpy(buffer, s.c_str(), MAX_PATH);
   return buffer;
}
__________________

C'ho certi cazzi Mafa' che manco tu che sei pratica li hai visti mai!
DanieleC88 è offline   Rispondi citando il messaggio o parte di esso
Old 27-07-2010, 11:15   #14
cionci
Senior Member
 
L'Avatar di cionci
 
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
Quote:
Originariamente inviato da DanieleC88 Guarda i messaggi
cionci è offline   Rispondi citando il messaggio o parte di esso
Old 27-07-2010, 11:22   #15
DanieleC88
Senior Member
 
L'Avatar di DanieleC88
 
Iscritto dal: Jun 2002
Città: Dublin
Messaggi: 5989
Toh, funziona!
Crea l'oggetto std::string corrispondente a partire dal contenuto di buffer? Perché se è così a quel punto conviene usare direttamente std::string, no?

ciao
__________________

C'ho certi cazzi Mafa' che manco tu che sei pratica li hai visti mai!
DanieleC88 è offline   Rispondi citando il messaggio o parte di esso
Old 27-07-2010, 11:30   #16
cionci
Senior Member
 
L'Avatar di cionci
 
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
Quote:
Originariamente inviato da DanieleC88 Guarda i messaggi
Toh, funziona!
Crea l'oggetto std::string corrispondente a partire dal contenuto di buffer? Perché se è così a quel punto conviene usare direttamente std::string, no?

ciao
Era un errore, non avevo messo il valore di ritorno corretto
cionci è offline   Rispondi citando il messaggio o parte di esso
Old 27-07-2010, 11:33   #17
DanieleC88
Senior Member
 
L'Avatar di DanieleC88
 
Iscritto dal: Jun 2002
Città: Dublin
Messaggi: 5989
E infatti così mi pareva, ma mi compila e funziona pure!
(Almeno, con clang, ora provo gcc...)
__________________

C'ho certi cazzi Mafa' che manco tu che sei pratica li hai visti mai!
DanieleC88 è offline   Rispondi citando il messaggio o parte di esso
Old 27-07-2010, 11:36   #18
cionci
Senior Member
 
L'Avatar di cionci
 
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
Quote:
Originariamente inviato da DanieleC88 Guarda i messaggi
E infatti così mi pareva, ma mi compila e funziona pure!
Che funzionasse era ovvio, visto che std::string ha i costruttori adatti per fare quella conversione
cionci è offline   Rispondi citando il messaggio o parte di esso
Old 27-07-2010, 11:40   #19
DanieleC88
Senior Member
 
L'Avatar di DanieleC88
 
Iscritto dal: Jun 2002
Città: Dublin
Messaggi: 5989
Be' quello sì, ma non ero certo che il compilatore facesse implicitamente la costruzione dell'oggetto senza lamentarsi.
Beata ignoranza.
__________________

C'ho certi cazzi Mafa' che manco tu che sei pratica li hai visti mai!
DanieleC88 è offline   Rispondi citando il messaggio o parte di esso
Old 27-07-2010, 11:56   #20
cionci
Senior Member
 
L'Avatar di cionci
 
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
In teoria, con il passaggio del buffer, la cosa più "pulita" sarebbe passare anche la dimensione del buffer stesso.
cionci è offline   Rispondi citando il messaggio o parte di esso
 Rispondi


Sony WF-1000X M6: le cuffie in-ear di riferimento migliorano ancora Sony WF-1000X M6: le cuffie in-ear di riferiment...
Snowflake porta l'IA dove sono i dati, anche grazie a un accordo con OpenAI Snowflake porta l'IA dove sono i dati, anche gra...
Sistema Mesh Roamii BE Pro: il Wi-Fi 7 secondo MSI Sistema Mesh Roamii BE Pro: il Wi-Fi 7 secondo M...
Recensione HUAWEI Mate X7: un foldable ottimo, ma restano i soliti problemi Recensione HUAWEI Mate X7: un foldable ottimo, m...
Nioh 3: souls-like punitivo e Action RPG Nioh 3: souls-like punitivo e Action RPG
Panasonic 55'' QLED con Dolby Vision e F...
TOP 250 PLUS e TOP 300 PLUS ritornano: v...
Incentivi auto elettriche, si va verso r...
Crimson Desert non è un Soulslike...
Sostituzione caldaia con nuovi sistemi, ...
La Germania verso il divieto e il ban de...
Questo super TV Samsung OLED da 65'' con...
Android Auto 16.3 svela due segreti di G...
Apple Podcasts introduce video con HLS e...
Gli iPhone 17, 17 Pro e 16e sono conveni...
Sentite l'Agenzia delle Entrate: le e-bi...
Recensione Synology DS1825+: 8 hard disk...
App IO: i numeri del portafoglio digital...
4 novità pesanti nelle offerte Am...
Kyndryl rafforza il SOC di Roma e apre i...
Chromium
GPU-Z
OCCT
LibreOffice Portable
Opera One Portable
Opera One 106
CCleaner Portable
CCleaner Standard
Cpu-Z
Driver NVIDIA GeForce 546.65 WHQL
SmartFTP
Trillian
Google Chrome Portable
Google Chrome 120
VirtualBox
Tutti gli articoli Tutte le news Tutti i download

Strumenti

Regole
Non Puoi aprire nuove discussioni
Non Puoi rispondere ai messaggi
Non Puoi allegare file
Non Puoi modificare i tuoi messaggi

Il codice vB è On
Le Faccine sono On
Il codice [IMG] è On
Il codice HTML è Off
Vai al Forum


Tutti gli orari sono GMT +1. Ora sono le: 13:52.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Served by www3v