2013-10-03 5 views
1

J'ai une configuration d'application client-serveur en utilisant QTcpServer et QTcpSockets et semble avoir d'énormes fuites de mémoire. Je me demande si le problème est dans mon utilisation des sockets de Qt parce que je viens de mettre en place une application de test simple et après avoir envoyé 250 millions de messages dans une boucle mon client s'élève à 75 mégaoctets. Il semble que si j'ai plusieurs millions de messages, je vois plus de 300 Mo de mémoire utilisée dans mon client.QTcpSocket fuite de mémoire

Cela ne me semble pas juste, car je continue d'envoyer des messages que la mémoire ne cesse de monter!

Donc devrais-je m'attendre à ce que mon application monte constamment en mémoire étant donné le code suivant sur un socket connecté. Si cette prise est laissée ouverte, je vais rapidement manquer de mémoire. Est-ce que je manque quelque chose?

if (socket && socket->isOpen()) 
{ 
    for(int i = 0; i < 25000000; ++i) { 
     QString str = "test"; 
     socket->write(str.toStdString().c_str()); 
    } 
} 
+0

Comment initialisez/assignant vous votre variable socket? Ajoutez plus de code si vous le pouvez. – Huy

Répondre

1

Cela est prévu car vous mettez potentiellement en mémoire tampon une grande quantité de données. Il s'agit d'une API asynchrone due à la boucle d'événements Qt, vous devez donc attendre l'écriture lorsque le programme est prêt pour cela.

Vous pouvez utiliser le signal void QIODevice::bytesWritten(qint64 bytes) [signal] pour continuer l'écriture. Si vous utilisez l'API async de cette façon, vous éviterez la consommation importante de mémoire.

+0

J'ai fatigué d'écrire les messages comme décrit ci-dessus et je suis d'accord avec le fait que le fait d'être tamponné augmentera la mémoire. Ce que j'ai omis d'ajouter, c'est que si j'attends une période de temps avec la boucle d'événements en cours (et donc l'envoi des messages), j'envoie (ou plutôt tampon) un autre paquet de messages que je vois doubler. Si j'attends encore et j'en envoie encore, la mémoire remonte encore. Comme les messages sont envoyés, la taille du tampon diminue sûrement? – user1818822

+0

@ user1818822: avez-vous connecté votre opération d'écriture en tant que slot au signal susmentionné? Ensuite, cela n'arrivera plus. – lpapp

+0

@ user1818822: avez-vous compris? – lpapp

0

Le socket est un tampon interne QIODevice, et tout ce que vous avez écrit est tamponné jusqu'à ce que la pile réseau puisse l'envoyer. Ce que vous voyez est un comportement attendu. Le write() est pas une opération de blocage, et de toute façon jamais faire des opérations de blocage dans votre thread graphique, sauf si vous pensez que les utilisateurs apprécient vraiment les applications avec une interface utilisateur morte.

Peut-être que vous voulez mettre votre écriture dans un slot qui est informé de la progression du socket? Les prises sont tous QIODevice. Regardez là pour les signaux utiles, par exemple bytesWritten(). Il est d'usage de différer l'écriture sauf si la valeur renvoyée par bytesToWrite() est inférieure à un seuil défini. Votre fente d'écriture pourrait commencer comme ceci:

// more than 2 pages worth of stuff still to send, we abstain 
if (socket->bytesToWrite() > 1<<13) return; 

pinailler: Le toStdString() est complètement grauituous. Vous devez utiliser:

socket->write(str.toUtf8().constData()); 

Peu importe que pour ces tests, vous pouvez trivialement créer un tableau d'octets sans utiliser une chaîne du tout:

const QByteArray testData(1000, ' '); // a 1000 spaces 
for (int i = 0; i < 100000; ++i) socket->write(testData);