Это может произойти сбой просто потому, что именно это (как правило, поведение не определено) происходит, когда вы пытаетесь освободить указатель, который не указывает на память, которая может быть освобождена.Подробнее о строковых литералах читайте здесь: https://stackoverflow.com/a/1704433/6699433
И оба ваших примера написаны очень плохо, поскольку malloc просто никогда не используется.
char* strings[100];
strings[0]=malloc(100);
char str[100]="AAA";
strings[0]=strdup(str);
free(strings[0]);
эквивалентно
char* strings[100];
char str[100]="AAA";
strings[0]=strdup(str);
free(strings[0]);
и
char* strings[100];
strings[0]=malloc(100);
strings[0]="AAA";
free(strings[0]);
эквивалентны
char* strings[100];
strings[0]="AAA";
free(strings[0]);
Обратите внимание, что «эквивалент» не на 100% корректен, поскольку у вас есть побочные эффекты.Я просто хотел показать, что некоторые строки абсолютно бессмысленны, так как вы не используете результат перед переназначением переменных.