質問

mallocしたときに、確保してない領域へも値を代入できて、出力もできるということに遭遇しています。確保してない領域を使ってそのようなことができる理由はなんなのでしょうか?
これだと予想しない挙動になって、バグの原因になったりしそうだなと思っていまして。

下記の場合、mallocでchar4つ分を確保してるので、p[0]からp[3]に書き込めるのは納得です。
一方で、p[4]とp[5]にも文字を書き込めて、その後の出力でも表示されます。

#include <iostream>

using namespace std;

int main () {
    char* p;
    p = (char*)malloc(sizeof(char)*4);

    p[0] = 'a';
    p[1] = 'b';
    p[2] = 'c';
    p[3] = 'd';
    // p[4], p[5]にも書き込めてしまう!
    p[4] = 'e';
    p[5] = 'f';

    cout << p << endl; // abcdef
    free(p);
}