blog > debugging segfaults with gdb (7 Dec 2025)

debugging segfaults with gdb

This "blogpost" is mainly just a reference/tutorial for my future self for when I'll have forgotten how to use gdb again.

I started using gdb to debug segfaults that occur on basdon, my gta:sa-mp server, which runs using things that I wrote in C.

Ensuring symbols are present #

plugins/basdonfly.so is my plugin for the samp server, which is built with gcc using -ggdb to try to ensure enough debug information is present.

Enabling coredumps #

I initially didn't get coredumps, so I had to execute ulimit -c unlimited. Maybe "unlimited" should be some sane value instead, but it works and I'm too lazy now. I also read that this is not persistent, so I simply run this command right before starting the sa:mp server every time.

With this configuration, I now get core.PID files on segfaults, where PID is the process id. They are placed in the working directory. I've also read somewhere - I think - that there may be a standard path set where these files will be put, but it's not like that in my case.

Launching gdb #

gdb /basdon-fly/server/samp03svr -c core.8492

I'm not sure what the correct program argument is, should it be the server executable or my plugin shared library? It does not seem to matter much, but there has to be a program argument or it doesn't show much.

A quick info sharedlibrary should confirm that my plugin library was loaded and included symbols and debug info:

(gdb) info sharedlibrary
From        To          Syms Read   Shared Object Library
		No          /lib/libdl.so.2
		No          /lib/libpthread.so.0
		No          /lib/libstdc++.so.6
		No          /lib/libm.so.6
		No          /lib/libgcc_s.so.1
		No          /lib/libc.so.6
0xf76f7058  0xf77124d3  Yes (*)     /lib/ld-linux.so.2
		No          plugins/mysql-r39-3-static.so
		No          /lib/librt.so.1
		No          /lib/libnss_files.so.2
		No          plugins/bcrypt-v2.2-debian7.so
		No          plugins/simplesocket.so
0xf633aa00  0xf635bdd3  Yes         plugins/basdonfly.so
(*): Shared library is missing debugging information.

A note on command shortening #

gdb finds commands using a "starts with" match, so info locals could be shortened by doing i lo.

If a command would be ambiguous, gdb will tell you.

Looking around #

At launch, gdb will already show the crash site.

Core was generated by `./samp03svr'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  spawn_get_random_spawn (playerid=playerid@entry=0,
outSpawnInfo=outSpawnInfo@entry=0xffd0c9a2) at spawn.c:118
118             memcpy(&outSpawnInfo->pos, spawns[klass] + spawnidx, sizeof(struct vec4));
[Current thread is 1 (LWP 8492)]

bt shows a backtrace

(gdb) bt
#0  spawn_get_random_spawn (playerid=playerid@entry=0, outSpawnInfo=outSpawnInfo@entry=0xffd0c9a2) at spawn.c:118
#1  0xf6348338 in natives_SpawnPlayer (playerid=playerid@entry=0) at samp.c:1443
#2  0xf6357cc3 in missions_cleanup (playerid=playerid@entry=0) at missions.c:820
#3  0xf6357e92 in missions_end_unfinished (playerid=playerid@entry=0, reason=reason@entry=1024) at missions.c:863
#4  0xf6357f5b in missions_on_vehicle_destroyed_or_respawned (vehicleid=vehicleid@entry=97) at missions.c:920
#5  0xf6357b8e in veh_DestroyVehicle (vehicleid=vehicleid@entry=97) at vehicles.c:1132
#6  0xf6359940 in B_OnVehicleSpawn (amx=0x84929d8, params=0xf63fd6a8 ) at basdonfly_callbacks.c:485
#7  0x08096a07 in ?? ()
#8  0x080a53b9 in ?? ()
#9  0x0814b674 in ?? ()
#10 0x0814cd5f in ?? ()
#11 0x080af078 in ?? ()
#12 0x080aa13a in ?? ()
#13 0xf73d91b3 in ?? ()

The frames in the backtrace are numbered, that number can be used to change the current context with frame <number>

(gdb) frame 1
#1  0xf6348338 in natives_SpawnPlayer (playerid=playerid@entry=0) at samp.c:1443
warning: Source file is more recent than executable.
1443            spawn_get_random_spawn(playerid, &spawnInfo);

info locals shows local variables in the current frame

(gdb) info locals
spawnInfo = {team = 11 '\v', skin = -13156097, _pad5 = 69 'E', pos = {coords = {x = -nan(0x50c9b8), y = 4.2606904e-34,
    z = 5.95649804e-34}, r = 1.35925951e-43}, weapon = {1764247626, -164267066, 139012568}, ammo = {-163641248, 8, 0}}

info args shows the arguments that were passed for the proc in the current frame

(gdb) info args
playerid = 0

print <expression> evaluates an expression. This can reference global and local variables, arguments, ...

(gdb) p player[playerid]->pos
$9 = {x = -15495.7988, y = 11682.5537, z = -1.38694525}

info types shows all known types (includes typedefs and structures)

info shows all info subcommands

ptype <name> shows a type definition

(gdb) ptype struct STREAMING_DATA
type = struct STREAMING_DATA {
    struct OBJECT_MAP *obj_map;
    struct RPCDATA_CreateObject *queued_objects[900];
    short num_queued_objects;
    struct ZONE_MAP *zone_map;
    short next_zone_idx;
}

(gdb) ptype enum OBJ_STREAM_MODE
type = enum OBJ_STREAM_MODE {OBJ_STREAM_MODE_ANY, OBJ_STREAM_MODE_CLOSEST_NOW}