SDL_INIT_JOYSTICK crashes if DInput gamepad plugged in

If I call SDL_Init() with SDL_INIT_JOYSTICK, and I already have a game controller plugged in, it crashes for me.
If no controller is plugged in, the SDL app runs fine. If a controller gets plugged in after it’s already started, it crashes in the same area.
(Note: my XBox 360 controller isn’t crashing - it functions fine. The non-XInput controllers are crashing).

I’m compiling SDL 2.0.7 (stable) with MinGW 5.3.0 (MinGW-W64) on Windows 10.
I’m linking against: -lmingw32 -lSDL2main -lSDL2 (are there any I’m missing?)
(Note this is just a test project to get it working. It’s just: http://lazyfoo.net/tutorials/SDL/20_force_feedback/index.php
with a few minor changes (i.e. removing SDL_image and using SDL_LoadBMP instead).

The debugger is telling me it crashes in SDL_dinputjoystick.c, in EnumJoystickCallback, though I don’t know precisely where (the debugger says line number 397, but I think the last two stackframes are wrong… The secondmost stackframe doesn’t match up with the function name it’s supposedly in).

The callstack is:
1 EnumJoysticksCallback SDL_dinputjoystick.c 397 0x6834293f
2 EnumJoysticksCallback SDL_dinputjoystick.c 295 0x68342cd3
3 ?? 0x719345b5
4 SDL_DINPUT_JoystickDetect SDL_dinputjoystick.c 483 0x68342f30
5 SDL_SYS_JoystickDetect SDL_windowsjoystick.c 349 0x68343a95
6 SDL_SYS_JoystickInit SDL_windowsjoystick.c 305 0x68343e9c
7 SDL_JoystickInit SDL_joystick.c 91 0x6832bd22
8 SDL_InitSubSystem_REAL SDL.c 198 0x68281935
9 SDL_Init_REAL SDL.c 241 0x68281935
10 init main.cpp 238 0x401939
11 SDL_main main.cpp 358 0x401c26
12 main_utf8 SDL_windows_main.c 126 0x402fb9
13 main_getcmdline SDL_windows_main.c 159 0x402fb9
14 WinMain *16 SDL_windows_main.c 202 0x4031a8
15 main 0x40346d

I’m not sure if it’s relevant or not, but SDL_SYS_JoystickDetect() in SDL_windowsjoystick.c passes a null pointer to SDL_DINPUT_JoystickDetect(), so EnumJoysticksCallback()'s ‘pContext’ is also null.

I’ve tried with two different DirectInput gamepads (a non-XInput Logitech and a PS4 controller) - both crash it. The Xbox 360 controller doesn’t crash, however, and works fine, being XInput.

I’ve tried using the pre-compiled MinGW libraries, same crash happens.

I’ve downloaded the latest (unstable) source using hg, compiled it, crashes at the same location.

I’m completely at a loss of how to proceed from here.

What confuses me, is with the line it (supposedly) crashes on I don’t see what could possibly make it crash:
dipdw2.diph.dwSize = sizeof(dipdw2);

[Edit:] If I put a simple printf() right before that line and recompile SDL, it runs fine and the DInput devices function well (or, at least I receive button presses from them). If I remove the printf() and recompile SDL, it crashes again.

I have zero idea why and am really confused by this behavior.

It looks like a memory corruption: a functions write to a memory location which belong to something else.

When you add a printf (or any other function or a variable) you modify the memory layout so the corruption affects an other object.

Most memory corruption are due to a “double free” or “use after free”. You should review your memory management. There are also tools to help you such as address sanitizer: https://clang.llvm.org/docs/AddressSanitizer.html (available for Clang and GCC, but not MinGW).

1 Like

Memory corruption is a good thought, but to be sure it’s not on my end, I made the code as minimalist as possible.

A fresh build from the latest repository, with no changes to SDL’s source, still crashes on the same line, even with this code:

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

int main(int argc, char *argv[])
{
if( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_JOYSTICK ) < 0 )
{
    std::cout << "SDL could not initialize! SDL Error: %s" << SDL_GetError() << std::endl;
    return 0;
}

std::cout << "Everything went fine." << std::endl;

SDL_Quit();
}

It crashes inside of SDL_Init() (in EnumJoysticksCallback()), only if a DirectInput controller is plugged in. It doesn’t matter which of the two separate DirectInput controllers (genuine PS4 or Logitech) - either controller crashes it, and the XInput one (genuine Xbox360 controller) does not.

It only crashes if a DirectInput controller is plugged in, and SDL_INIT_JOYSTICK is in SDL_Init(). Without SDL_INIT_JOYSTICK, it doesn’t crash, even if a controller is plugged in.

If no-one else is encountering this issue, it must be a problem on my end, but I’m not sure what. Maybe I’m compiling SDL wrong, somehow? I use CMake to generate the makefile, and mingw32-make to build it.

I link against: -lmingw32 -lSDL2main -lSDL2

this should be <SDL2/SDL.h>

1 Like

Naw, that’s the correct folder that I named when copying SDL’s headers to where I wanted them - the same folder that I tell MinGW where to find SDL, which it does do successfully.

I’m pretty sure it wouldn’t be able to compile if it wasn’t correct (even if SDL 1.x was installed at the location - which it isn’t - I don’t have SDL 1.x’s headers on this machine), so I don’t think that’s the issue.

What is the error you get when your program crash? I guess a segmentation fault because pContext is NULL (even if the backtrace show the wrong line). SDL_SYS_JoystickDetect() pass the address of a variable on the stack to SDL_DINPUT_JoystickDetect so it shouldn’t be NULL.

You can try to put a breakpoint on EnumJoysticksCallback(), check that pContext isn’t NULL yet. Then put a watchpoint on pContext with the watch command. gdb will automatically stop when something try to write to pContext, print the backtrace and you get the name of the function that corrupt the memory.

1 Like

Yea, it’s a segmentation fault - I should’ve mentioned that, oops!
I really appreciate the help you’ve provided, thank you.

pContext is passed into EnumJoysticksCallback null, I think. Leastwise that’s what MinGW’s GDB is showing.

Following it back, it’s null in SDL_DINPUT_JoystickDetect too, though that’s a pointer-to-pointer and GDB is for some reason showing it just as a regular pointer.

Which is weird, because the code that calls SDL_DINPUT_JoystickDetect looks like this:

pCurList = SYS_Joystick;
SYS_Joystick = NULL;

/* Look for DirectInput joysticks, wheels, head trackers, gamepads, etc.. */
SDL_DINPUT_JoystickDetect(&pCurList);

…so pContext should be a non-null pointer pointing to pCurList, and pCurList should - I think? - be null.
I can’t see where SYS_Joystick is being initialized though. The debugger says it’s null, but I don’t see why it isn’t gibberish (other than debug build).

But it doesn’t seem to be crashing on pContext anyway - it doesn’t even reach it. It really does seem to crash on dipdw2.diph.dwSize = sizeof(dipdw2);, though I haven’t a clue why!

(Highlighted line is where the crash occurs - the two red dots were breakpoints I had set)

It must be something weird on my end, probably with how I’m compiling SDL, or the compiler settings on MinGW.

Anyway, I was looking into using SDL purely for gamepad support for my SFML application, but I’ve ended up solving my gamepad-related needs via a different method (just coding a button/axis mapping system myself), and so I no longer need SDL for that.

Thank you for your help - while I’m curious about the cause of the crash, I don’t want to waste more of your time than what you’ve already generously provided. I really do appreciate it!

Crashing on a movaps instruction is likely to be due to an alignment error (although I might have hoped the message would be more specific than ‘segmentation fault’). In this case, if the stack pointer esp is not 16-byte aligned that instruction will fault. If that’s the cause it could result from any function in the call stack failing to maintain correct stack alignment - so it could be a long way away from that code!

Is your compiler up-to-date? If there’s a later version than the one you are using, I would suggest trying that to see if it helps.

1 Like

I’m using MinGW 5.3.0, compiled by the MinGW-W64 project, shipped with QtCreator (the IDE I use) - there are newer versions available, though I wasn’t going to upgrade for another few months…

I’ve been using this MinGW install very heavily since last September - four months ago - and nothing else has noticeably gone wrong (including compiling and actively using SFML, Boost, a few smaller dynamic libs, and my own static libraries).

It’s possible my MinGW install is borked, and I do have multiple versions of MinGW installed, so it’s feasible that the commands I’m issuing to build SDL are accidentally being picked up by a different compiler version than the one being used to build the project, maybe creating an ABI mismatch… Odd that this hasn’t occurred with any other library I’ve built, though, but weirder alignment of bytes have occurred.

Whenever I do get around to updating my compiler, in several months, I’ll uninstall every compiler I have installed, update to the latest MinGW, and then I’ll try building and running SDL again.
I can’t do that right now, though, so I guess that puts this at a dead-end for the time being.

Thank you again for the help, gents, I’ll have to revisit this issue in the coming months.

Did you get a register dump with the crash report? If so, look at the value of esp at the time of the crash; if it is anything other than a multiple of 16 (i.e. the hexadecimal value doesn’t end in a zero) it confirms this as the cause of the crash. It doesn’t tell you why the stack pointer is misaligned of course, but it takes you forward. If it is a multiple of 16 then this is a red herring and the cause is elsewhere.

1 Like

I don’t have a crash dump, but I do see the register values at the time of the crash while stepping through it.

esp is hex 0x0060F37C, which is 6353788 in decimal (not a multiple of 16).

So the alignment fault is definitely the cause of the crash (had the compiler generated the movups instruction rather than movaps it would have worked). Unless you are linking in some binary code created in a different tool chain, it is suggestive of a compiler bug.

1 Like

Thank you - it’s very good to know the cause.