Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: [Bug?] std::string on Packets crashes on Windows but not Linux (mingw/g++)  (Read 8242 times)

0 Members and 1 Guest are viewing this topic.

MorleyDev

  • Full Member
  • ***
  • Posts: 219
  • "It is not enough for code to work."
    • View Profile
    • http://www.morleydev.co.uk/
Hello. So I want to make sure this isn't me doing something stupid or previously mentioned before I open an issue on it.

The following code will run on Linux perfectly, but on Windows (using the nuwen distribution of MinGW) the code compiles but crashes when trying to deserialise the string from the code. Changing it to a sf::String works, so that's a potential workaround. std::wstring will crash too, despite the documentation listing it as supported.

#include <SFML/Network.hpp>
#include <cstdint>
#include <iostream>
#include <stdexcept>

inline std::uint16_t getFreePort()
{
        sf::TcpListener listener;
        listener.listen(sf::TcpListener::AnyPort);
        return listener.getLocalPort();
}
       
int main(int nArgs, char** ppcArgs)
{
        typedef std::string PacketData;
        auto generatePacketData = []() { return PacketData("Hello_World"); };
        auto printPacketData = [](std::ostream& stream, PacketData data) { stream << data; };
       
        const auto port = getFreePort();
        const std::string ip = "127.0.0.1";
       
        std::cout << "Listener listens" << std::endl;
        sf::TcpListener listener;
        if ( listener.listen(port) != sf::Socket::Status::Done )
                throw std::runtime_error("Could not listen on port " + std::to_string(port));
        listener.setBlocking(false);
       
        std::cout << "Client Socket Connects" << std::endl;
        sf::TcpSocket clientSocket;
        if ( clientSocket.connect(sf::IpAddress(ip), port) != sf::Socket::Status::Done )
                throw std::runtime_error("Could not connect to listener on port " + std::to_string(port));
        clientSocket.setBlocking(false);

        std::cout << "Waiting for networking overhead" << std::endl;
        sf::sleep(sf::seconds(1));
       
        std::cout << "Server accepts" << std::endl;
        sf::TcpSocket serverSocket;
        if ( listener.accept(serverSocket) != sf::Socket::Status::Done )
                throw std::runtime_error("Could not accept listener on port " + std::to_string(port));
        serverSocket.setBlocking(false);
       
        const PacketData inData = generatePacketData();
       
        std::cout << "Client sends packet" << std::endl;
        sf::Packet sendPacket;
        sendPacket << inData;
        clientSocket.send(sendPacket);
       
        std::cout << "Server receives packet" << std::endl;
        sf::Packet receivePacket;
        const auto status = serverSocket.receive(receivePacket);
       
        PacketData outData;
        switch(status)
        {
        case sf::Socket::Status::Done:
                std::cout << "Server received packet" << std::endl;
                receivePacket >> outData;
                std::cout << "Server clears packet" << std::endl;
                receivePacket.clear();
                break;

        default:
                throw std::runtime_error("Did not receive packet");
        }
       
        std::cout << "Received packet: ";
        printPacketData(std::cout, outData);
        std::cout << std::endl;
       
        return 0;
}
 

Am I missing something obvious, is std::string/std::wstring not supported with sf::Packet and it crashes or just works because of some overloading nonsense, or is it a known (or unknown) bug in sf::Packet?

Whilst I can use the sf::String solution, a compiler error would of been be nicer than my roundtrip tests of my SFML wrappers crashing (not failing, just straight up crashing) and me having to break out the debugger because of this unintuitive gotcha in SFML's packets.
« Last Edit: March 21, 2014, 06:27:24 pm by MorleyDev »
UnitTest11 - A unit testing library in C++ written to take advantage of C++11.

All code is guilty until proven innocent, unworthy until tested, and pointless without singular and well-defined purpose.

antytaon

  • Newbie
  • *
  • Posts: 6
    • View Profile
    • Email
I just wanted to start new topic about this issue.
I have similar problem. I can send packets consisting of char array and everything works fine. But when I just use:
sf::Packet packet;
packet << "smth";
my programm crashes at second line. No operator overloading works. I am using Windows and cannot test it on linux right now.

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10819
    • View Profile
    • development blog
    • Email
Haven't investigated (yet), but it sounds like some encoding issue, thus it might be useful to provide the encoding of your source files and how the compiler treats "string" constances. ;)
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

antytaon

  • Newbie
  • *
  • Posts: 6
    • View Profile
    • Email
I got problem with:
sf::IpAddress address = client->getRemoteAddress();
std::cout << address;
std::string ipA = address.toString(); // this line crashes
The last line crashes too, can it be linked to previous situation?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
It looks like a bad mix of C++ runtimes. What is your compiler?
Laurent Gomila - SFML developer

antytaon

  • Newbie
  • *
  • Posts: 6
    • View Profile
    • Email
I use Microsoft Visual Studio 2013 and I build app with x64 configuration.

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10819
    • View Profile
    • development blog
    • Email
And you've built SFML manually, right? There are no VS 2013 packages.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

antytaon

  • Newbie
  • *
  • Posts: 6
    • View Profile
    • Email
Aww forgot about it. I will do this now and tell you about results :)
EDIT: Big thanks, building SFML from source code brought working strings in VS 2013  :D
« Last Edit: March 22, 2014, 10:17:05 am by antytaon »

MorleyDev

  • Full Member
  • ***
  • Posts: 219
  • "It is not enough for code to work."
    • View Profile
    • http://www.morleydev.co.uk/
I'm using the latest version of the nuwen mingw distribution. I rebuilt SFML again to make sure I hadn't accidentally updated the compiler and not SFML, but the crash still happens.

I found a work around in passing an std::string to an sf::String and serialising the sf::String on send, and deserialising to another sf::String and then extracting the std::string from the sf::String via toAnsiString on receive.
« Last Edit: March 22, 2014, 02:45:20 pm by MorleyDev »
UnitTest11 - A unit testing library in C++ written to take advantage of C++11.

All code is guilty until proven innocent, unworthy until tested, and pointless without singular and well-defined purpose.

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
You could try running:
#include <iostream>
#include <string>
#include <SFML/Network.hpp>

int main() {
        std::cout << "sf::Uint32: " << sizeof(sf::Uint32) << "\n";
        std::cout << "std::string::value_type: " << sizeof(std::string::value_type) << "\n";
        std::cout << "std::wstring::value_type: " << sizeof(std::wstring::value_type) << "\n";
}
to rule out any exotic data type sizes.

I don't know if it would make sense making the string serialization/deserialization more uniform in that it packs the characters into sf::Uint32s regardless of what kind of string it receives. It would make it less of an adventure when trying to communicate between hosts which for some reason might not have the same idea of how big a certain type should be. There will be a bit more overhead, yes. However, considering the bulk of the data flow in a typical application shouldn't consist of strings being transferred, the impact will be barely noticeable.
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

MorleyDev

  • Full Member
  • ***
  • Posts: 219
  • "It is not enough for code to work."
    • View Profile
    • http://www.morleydev.co.uk/
sizeof(sf::Uint32) = 4
sizeof(std::string::value_type) = 1
sizeof(std::wstring::value_type) = 2
Seems like pretty standard sizes to me.

As an aside, you say strings won't compose much of networking, but I would like to note that client/server communication via JSON isn't that uncommon in games.
UnitTest11 - A unit testing library in C++ written to take advantage of C++11.

All code is guilty until proven innocent, unworthy until tested, and pointless without singular and well-defined purpose.

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Let's just say... if you wanted to minimize delay and maximize throughput you wouldn't be using something like JSON as your primary communication medium...
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
...you would use XML ;D

(actually, it's amazing how a format of this verbosity could become so popular)
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

MorleyDev

  • Full Member
  • ***
  • Posts: 219
  • "It is not enough for code to work."
    • View Profile
    • http://www.morleydev.co.uk/
My point was more that for your average modern 2-4 player game, JSON would be "sufficient enough" for usage.

But anyway getting distracted...has anybody actually tried this code on their setup? :S Because if it's not just happening for me, the only reason I can think for it failing is some DLL/EXE boundary shenanigans.

But I can pass it to an sf::String constructor just fine, and get the value from toAnsiString, and aren't they both crossing the System DLL boundary?
« Last Edit: March 23, 2014, 04:48:29 pm by MorleyDev »
UnitTest11 - A unit testing library in C++ written to take advantage of C++11.

All code is guilty until proven innocent, unworthy until tested, and pointless without singular and well-defined purpose.

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Did you try running debug and checking whether the stuff going on inside operator>> and operator<< is sane? If the standard library is called with bogus parameters it can't really help but crash.
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).