CONNEXION
  • RetourJeux
    • Sorties
    • Hit Parade
    • Les + populaires
    • Les + attendus
    • Soluces
    • Tous les Jeux
    • Gaming
  • RetourActu Gaming
    • News
    • Astuces
    • Tests
    • Previews
    • Toute l'actu gaming
  • RetourBons plans
    • Bons plans
    • Bons plans Smartphone
    • Bons plans Hardware
    • Bons plans Image et Son
    • Bons plans Amazon
    • Bons plans Cdiscount
    • Bons plans Decathlon
    • Bons plans Fnac
    • Tous les Bons plans
  • RetourJVTech
    • Actus High-Tech
    • Intelligence Artificielle
    • Smartphones
    • Mobilité urbaine
    • Hardware
    • Image et son
    • Tutoriels
    • Tests produits High-Tech
    • Guides d'achat High-Tech
    • JVTech
  • RetourCulture
    • Actus Culture
    • Culture
  • RetourVidéos
    • A la une
    • Gaming Live
    • Vidéos Tests
    • Vidéos Previews
    • Gameplay
    • Trailers
    • Chroniques
    • Replay Web TV
    • Toutes les vidéos
  • RetourForums
    • Hardware PC
    • PS5
    • Switch 2
    • Xbox Series
    • Switch
    • Pokemon pocket
    • FC 25 Ultimate Team
    • League of Legends
    • Tous les Forums
  • PC
  • PS5
  • Xbox Series
  • Switch 2
  • PS4
  • One
  • Switch
  • iOS
  • Android
  • MMO
  • RPG
  • FPS
En ce moment Genshin Impact Valhalla Breath of the wild Animal Crossing GTA 5 Red dead 2
Liste des sujets

CPP / Boost::asio, internal error

Raidden36
Raidden36
Niveau 6
26 novembre 2019 à 00:07:52

Bonjour à tous,

Je dois coder un jeu en réseau en CPP sur un projet d'école. Le jeu doit être capable d'hoster des lobby qui eux-même peuvent lancer une partie (donc le serveur doit pouvoir gérer plusieurs parties en ligne).

Je m'occupais de l'intégration d'une classe serveur UDP dans l'une de mes autre classes (qui marchait très bien pendant la phase de test, donc avec un main de test) et...

../nptl/pthread_mutex_lock.c:427: __pthread_mutex_lock_full: Assertion `INTERNAL_SYSCALL_ERRNO (e, __err) != ESRCH || !robust' failed.

Je me retrouve d'un coup avec cet erreur, une internal de boost. Tout débug me renvoyant systématiquement directement à la lib et non à mon code, je me retrouve avec un certain problème de compréhension.

Quelqu'un de familier avec boost a-t-il déjà eu ce soucis ?

Infos utiles :

Cette façon ne génère pas d'erreurs, et fonctionne très bien


int main()
{
   boost::asio::io_service io_service;
   udp_serv server_udp(io_service);
   io_service.run();
}

celle-ci génère le crash:


class wrapper {
  public:
  wrapper() : udp_server(io_service_) 
     {
        io_service_.run();
     }
  
  boost::asio::io_service io_service_;
  udp_serv udp_server;
};
Message édité le 26 novembre 2019 à 00:09:38 par Raidden36
godrik
godrik
Niveau 30
26 novembre 2019 à 00:42:11

Je n'ai jamais regarder asio. Mais je veux bien jetter un oeil.
Donne un code complet qui marche et un code complet qui crash.

Raidden36
Raidden36
Niveau 6
26 novembre 2019 à 12:57:51

Après un peu de refacto pour que tout tienne en un fichier et soit compréhensible sans mon archi:

voilà qui fonctionne

#include <iostream>
#include <string>
#include <boost/array.hpp>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/asio.hpp>

using boost::asio::ip::udp;

class udp_server
{
public:
  udp_server(boost::asio::io_service& io_service)
    : socket_(io_service, udp::endpoint(udp::v4(), 13))
  {
    start_receive();
  }

private:
  void start_receive()
  {
    socket_.async_receive_from(
        boost::asio::buffer(recv_buffer_), remote_endpoint_,
        boost::bind(&udp_server::handle_receive, this,
          boost::asio::placeholders::error,
          boost::asio::placeholders::bytes_transferred));
  }

  void handle_receive(const boost::system::error_code& error,
      std::size_t /*bytes_transferred*/)
  {
    if (!error || error == boost::asio::error::message_size)
    {
      boost::shared_ptr<std::string> message(
          new std::string("test"));

      socket_.async_send_to(boost::asio::buffer(*message), remote_endpoint_,
          boost::bind(&udp_server::handle_send, this, message,
            boost::asio::placeholders::error,
            boost::asio::placeholders::bytes_transferred));

      start_receive();
    }
  }

  void handle_send(boost::shared_ptr<std::string> /*message*/,
      const boost::system::error_code& /*error*/,
      std::size_t /*bytes_transferred*/)
  {
  }

  udp::socket socket_;
  udp::endpoint remote_endpoint_;
  boost::array<char, 1> recv_buffer_;
};

int main()
{
  try
  {
    boost::asio::io_service io_service;
    udp_server server(io_service);
    io_service.run();
  }
  catch (std::exception& e)
  {
    std::cerr << e.what() << std::endl;
  }

  return 0;
}

Voilà qui ne fonctionne pas:
// udp_server.cpp //


#include "udp_server.hpp"

  void udp_server::start_receive()
  {
    socket_.async_receive_from(
        boost::asio::buffer(recv_buffer_), remote_endpoint_,
        boost::bind(&udp_server::handle_receive, this,
          boost::asio::placeholders::error,
          boost::asio::placeholders::bytes_transferred));
  }

  void udp_server::handle_receive(const boost::system::error_code& error,
      std::size_t /*bytes_transferred*/)
  {
    if (!error || error == boost::asio::error::message_size)
    {
      boost::shared_ptr<std::string> message(
          new std::string("test"));

      socket_.async_send_to(boost::asio::buffer(*message), remote_endpoint_,
          boost::bind(&udp_server::handle_send, this, message,
            boost::asio::placeholders::error,
            boost::asio::placeholders::bytes_transferred));

      start_receive();
    }
  }

  void udp_server::handle_send(boost::shared_ptr<std::string> /*message*/,
      const boost::system::error_code& /*error*/,
      std::size_t /*bytes_transferred*/)
  {
  }

//udp_server.hpp //

#ifndef UDP_SERVER_HPP_
#define UDP_SERVER_HPP_

#include <ctime>
#include <iostream>
#include <string>
#include <boost/array.hpp>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/asio.hpp>

using boost::asio::ip::udp;

class udp_server
{
public:
  udp_server(boost::asio::io_service& io_service)
    : socket_(io_service, udp::endpoint(udp::v4(), 13))
  {
    start_receive();
  }
private:
  void start_receive();
  void handle_receive(const boost::system::error_code& error,
      std::size_t /*bytes_transferred*/);

  void handle_send(boost::shared_ptr<std::string> /*message*/,
      const boost::system::error_code& /*error*/,
      std::size_t /*bytes_transferred*/);

  udp::socket socket_;
  udp::endpoint remote_endpoint_;
  boost::array<char, 1> recv_buffer_;
};
#endif /* !UDP_SERVER_HPP_ */

// world.hpp (le wrapper) //

#ifndef WORLD_HPP_
#define WORLD_HPP_

#include "udp_server.hpp"

class world {
    public:
        world()
            : udp_server_(io_service_)
            {
                io_service_.run();
            }
        udp_server udp_server_;
        boost::asio::io_service io_service_;
        //std::vector<std::shared_ptr<session>> player_pool;
};

#endif /* !WORLD_HPP_ */

// main.cpp //


#include "world.hpp"

int main()
{
    world w;
}

Flag de compilation -lboost_system requis.

En faisant de la refacto et en passant le code qui ne fonctionne pas en un seul fichier, ça le fait fonctionner. J'imagine donc que j'ai des problèmes avec mes includes ? Je ne sais pas trop. Voici le code avec le wrapper en one file qui fonctionne:

#include <iostream>
#include <string>
#include <boost/array.hpp>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/asio.hpp>

using boost::asio::ip::udp;

class udp_server
{
public:
  udp_server(boost::asio::io_service& io_service)
    : socket_(io_service, udp::endpoint(udp::v4(), 13))
  {
    start_receive();
  }

private:
  void start_receive()
  {
    socket_.async_receive_from(
        boost::asio::buffer(recv_buffer_), remote_endpoint_,
        boost::bind(&udp_server::handle_receive, this,
          boost::asio::placeholders::error,
          boost::asio::placeholders::bytes_transferred));
  }

  void handle_receive(const boost::system::error_code& error,
      std::size_t /*bytes_transferred*/)
  {
    if (!error || error == boost::asio::error::message_size)
    {
      boost::shared_ptr<std::string> message(
          new std::string("test"));

      socket_.async_send_to(boost::asio::buffer(*message), remote_endpoint_,
          boost::bind(&udp_server::handle_send, this, message,
            boost::asio::placeholders::error,
            boost::asio::placeholders::bytes_transferred));

      start_receive();
    }
  }

  void handle_send(boost::shared_ptr<std::string> /*message*/,
      const boost::system::error_code& /*error*/,
      std::size_t /*bytes_transferred*/)
  {
  }

  udp::socket socket_;
  udp::endpoint remote_endpoint_;
  boost::array<char, 1> recv_buffer_;
};

class wrapper {
    public:
        wrapper() : server(io_service)
        {
            io_service.run();
        }
        boost::asio::io_service io_service;
        udp_server server;
};

int main()
{
  try
  {
    wrapper w;
  }
  catch (std::exception& e)
  {
    std::cerr << e.what() << std::endl;
  }

  return 0;
}

Ou peut être un petit détail que j'aurais loupé ? Merci de regarder en tous cas.

Raidden36
Raidden36
Niveau 6
26 novembre 2019 à 15:48:06

Ceci-dit avec la refacto one file ça marche donc... On va considérer le problème comme résolu, même si je reste curieux de savoir ce qui allait pas avant.

godrik
godrik
Niveau 30
26 novembre 2019 à 17:15:18

Ah, c'est bien ce a quoi je m'attendais, c'est un probleme d'ordre de construction. Ce qui m'a mis la puce a l'oreille, c'est l'erreur produite par valgrind, de la memoire pas initialise dans l'utilisation d'un mutex.

Tu rencontre une erreur typique de C++ qui apparait principalement quand on essaye de faire trop de chose a la construction.
Ca m'etonne que ton compilateur ne t'ai pas averti. g++ 8.3 produit un warning avec -Wall

world.hpp est ecrit comme ca:

#ifndef WORLD_HPP_
#define WORLD_HPP_

#include "udp_server.hpp"

class world {
    public:
        world()
            : udp_server_(io_service_)
            {
                io_service_.run();
            }
        udp_server udp_server_;
        boost::asio::io_service io_service_;
        //std::vector<std::shared_ptr<session>> player_pool;
};

#endif /* !WORLD_HPP_ */

En C++ les objets sont construit dans l'ordre de leur declaration dans la class. Donc udp_server_ est construit avant io_service_. Quel que soit l'ordre dans lequel tu listes les variables dans la liste d'initialisation du constructeur, les variables sont toujours construite dans l'ordre de declaration dans l'objet. Certaine version de C++ rejettais meme les listes d'initialisation qui n'etait pas dans l'ordre d'apparence dans l'objet.
Comme udp_server_ apparait avant io_service_ dans l'objet, il est cree en premier. Le constructeur passe une reference a io_service_ au constructeur de udp_serveur_, mais io_service_ n'est pas encore construit. Donc l'execution du constructeur de udp_server_ se chie dessus.

Inverse l'ordre des deux variables dans l'objet world, et la construction devient correcte.

C'est pour ca que les gens veulent avoir un code complet pour debugger. Il y a des erreurs subtiles parfois.

Raidden36
Raidden36
Niveau 6
26 novembre 2019 à 17:20:59

D'accord ! Et du coup lors de ma refacto j'ai par pur hasard mis les deux variables dans un ordre inversé et ça avait donc marché.

Très bon à savoir, moi qui est beaucoup plus l'habitude du C que du CPP, je n'y aurais jamais pensé.

Sous forums
  • Aide à l'achat Mac
  • Internet
  • Macintosh
  • Création de sites web
  • Création de Jeux
  • Linux
  • Programmation
  • Steam Deck
  • Hardware
La vidéo du moment