SDL_Log oddity (%p)

On 64-bit Windows, using the pre-compiled SDL2.dll (from SDL2-2.28.5-win32-x64.zip), SDL_Log() with the %p format specifier is outputting only 32-bits rather than 64-bits. So for example this code:

SDL_Log("q = 0x%p\n", q);

is outputting “INFO: q = 0x7bddf60” when q is a char* with the value 0x1BA07BDDF60. I find this very strange, any ideas?

Hmm. Here’s three ways to print an address (C++), do all of these show the same address?

#include <SDL2/SDL.h>
#include <stdio.h>
#include <iostream>

int main()
{
	SDL_Init(SDL_INIT_EVERYTHING);
	size_t thing = 12;
	SDL_Log("Address: %p", &thing);
	printf("Printf Address: %p\n", &thing);

	size_t val = reinterpret_cast<size_t> (&thing);
	std::cout << std::hex << val;

	std::cout << std::endl;
	SDL_Quit();
}

My first laymen’s guess is that any leading zeroes might be getting stripped away, and I’m not sure how to confirm or disprove that guess.
My other guess is perhaps your compiler is building 32 bit code? (I’m pretty sure X86_64 Windows will swap to compatibility mode 32 bit environment to run 32 bit code natively).
Here’s a way to check if your compiler is building 64 bit code (see the second answer):

It’s a bug. Was fixed in 1ab452fc5776e7c34834388d7fbd806c8dcc198b tho.
SDL uses its own vsnprintf (SDL_vsnprintf) implementation for official Windows builds, which contained an error.
The fix is not yet in release… You have to build the edge or build this release with ANSI printf.
The build from the MSYS2 MinGW repository uses the ANSI printf implementation, not the SDL one, and doesn’t have this error.

OK, but I always use the pre-compiled DLLs. I’m not about to switch to building SDL2 from source at this stage! Presumably it will be fixed in SDL2, I can’t use SDL3.

You can grab the build that uses ANSI printf at https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-SDL2-2.28.5-1-any.pkg.tar.zst
SDL2.dll from this build has no extra dynamic dependencies and fully ABI compatible with the official one, so it can be used as drop-in replacement.

Thanks, but (unhelpfully) SDL_Log() isn’t writing anything to the Windows console when I use that DLL! The message seems to be disappearing into thin air, maybe stderr (if that’s where it goes to) is handled differently in that build?

Sounds like your application uses GUI subsystem, you should compile it as console application to get standard output on Windows: -mconsole for gcc, /SUBSYSTEM:console for MSVC (or subsystem setting in linker options for Visual Studio).
Btw SDL_Log on Windows sends message to debugger using OutputDebugString, so you can read the messages from the debugger no matter if console allocated or not.

This condition is not met for builds with ANSI stdio, so SDL_LogMessageV doesn’t not attach to the parent console. It looks rather questionable for me…

I don’t need to do that when I use the ‘official’ DLL, which I’ve now changed back to. With that, SDL_Log() outputs to the console with my normal (GUI) build, which is more convenient than needing to create a special debug build.

Because of “hack” mentioned above. I believe it’s a bug to not attach console on Windows there.
You have to wait release with printf fix then, sorry that my solution didn’t work for you, but I hope this info was helpful.

@ rtrussel: I’m a tad confused by your previous post.
Are you still having issues with the bug, or do you have things working now?

I was really curious if either printf or the C++ reinterpret cast would work for you as alternatives?

As to the bug: Why not fix it in the source and build/compile the lib?
I know that you are kind of stuck with this being the last compatible version for your desired hardware… but I have seen how much work you’ve put into your project, why not fork the official SDL source and improve the version that you are stuck with?

I was using SDL_Log() to try to trace an obscure bug in my code, and the 32-bit truncation led me down a blind alley. It was a major time-waster!

Eventually I found the actual bug (an obscure and unexpected difference in the behavior of the strtoull() function between platforms) so I no longer need SDL_Log() and the %p issue has ceased to be relevant.

The main reason (apart from the sheer hassle factor) is that I could only realistically do that in Windows; in MacOS I use the distributed SDL2 Framework and in Linux/PiOS I use the version of SDL2 available from the repository.

So I’d rather use an ‘official’ binary everywhere (except in Android and iOS where there is no such thing, as far as I know, and I have no choice but to build SDL2 from source).

I was thinking about your current situation (stuck in a certain lib version), and I had another really bad idea.

I dynamically linked SDL3’s SDL_Log function back into this code compiled with SDL2.
I tested it for SDL_Log and it worked.
I just don’t know how far you would be able/willing to apply it.

#include <SDL2/SDL.h>

void (*NEW_Log)(SDL_PRINTF_FORMAT_STRING const char *fmt, ...);

int main()
{
	int val = 12;
	SDL_Init(SDL_INIT_EVERYTHING);

	void * handle = SDL_LoadObject("libSDL3.so.0.0.0");
	NEW_Log = (void (*)(const char *, ...)) SDL_LoadFunction(handle, "SDL_Log");
	NEW_Log("Here's the address: %p", &val);
	SDL_UnloadObject(handle);

	SDL_Quit();
}

(I used a *.so file for my tests on Linux. It should work similarly with Windows *.dll files. I do not know if SDL3 fixes the specific SDL_Log issue, but the general idea is to pull anything useful that you can from SDL3 when it gets stable-released.)
There’s obviously certain functions that can’t mix and match, but I think a large chunk of the two libs are still very compatible. At least it could be an option.