En typ av buggar som kan skapa rätt svåra buggar är off-by-one, användning av dangling pointers och liknande. Språk som Java, C#, Ruby, Python m.fl. lägger ju in tester mot att läsa/skriva utanför allokerat utrymme och de hanterar minne automatiskt.
Men finns fortfarande många problem där språk som C och C++ är och förblir toppvalet, fram till nu har man fått balansera på slak lina för att inte omedvetet orsaka problemen listade ovan.
Ni som har en Skylake eller senare har en funktion som kallas MPX, Memory Protection Extensions.
Kolla in detta program
/* -*- compile-command: "make CFLAGS=\"-mmpx -static-libmpx -fcheck-pointer-bounds -g -O0\" main" -*- */
#include <stdio.h>
#include <stdint.h>
typedef struct data_st
{
uint32_t pad1;
uint32_t buff;
uint32_t pad2;
} DATA;
void foo(uint8_t *b)
{
b[0] = 0xa;
b[1] = 0xb;
b[2] = 0xc;
b[3] = 0xd;
b[4] = 0xde; /* skriver en byte bakom det utrymme jag får använda! */
b[-1] = 0xad; /* skriver en byte framför det utrymme jag får använda! */
}
void bar(uint32_t *d)
{
foo ((uint8_t *) d);
}
int main()
{
DATA data = { 0, 0, 0 };
bar (&data.buff);
printf ("data.pad1 = %#x\n", data.pad1);
printf ("data.buff = %#x\n", data.buff);
printf ("data.pad2 = %#x\n", data.pad2);
}
Kör man detta på normalt sätt får man utskriften
data.pad1 = 0xad000000
data.buff = 0xd0c0b0a
data.pad2 = 0xde
Funktionen foo() skriver utanför både framför och bakom de 4 bytes som *b egentligen pekar på. I detta fall kraschar det inte då jag lagt en pad framför och bakom. Men det är en BUG!
Kolla nu vad som händer om man slår på MPX
Saw a #BR! status 1 at 0x4015e3
Saw a #BR! status 1 at 0x4015f7
data.pad1 = 0xad000000
data.buff = 0xd0c0b0a
data.pad2 = 0xde
Trots att C-pekaren *b rent syntaktiskt totalt saknar information om hur stort område som pekas på upptäcks ändå både fallet där man skriver en byte före och en byte efter det område som initialt skickades till bar().
Kör jag detta i en debugger blir det ännu coolare, i det läget blir det som om man satt en brytpunkt precis innan man gör en minnesöverskrivning. "#BR" står just för att MPX upptäcker detta fel och genererar en "break-point trap".
Beskrev denna finnes på jobbet, har nog aldrig varit så lätt att få de som håller i pengarna att köpa in nya maskiner då jag pekade fördelen att ha detta på de maskiner som kör våra automatiskt unit-tester!