Массив указателей на динамические массивы символов

Нужно создать массив указателей на массивы символов. Символы вводятся пользователем, а массив символов заканчивается символом новой строки. Все пробелы и табуляции удаляются.

Код:

#include<stdio.h>
#include<stdlib.h>

#define SIZE 1024
#define ARR_SIZE 1024


int main ( void )
{
    char c;
    char string[SIZE];
    char *pmt;
    char *arr[ARR_SIZE];
    int i = 0;
    int j = 0;
    int x;
    while ( (c = getchar()) != EOF )
    {
        if ( c != ' ' && c != '\t' )
        {
            if ( c == '\n' )
            {
                string[i] = '\0';
                pmt = (char*) malloc(i + 1);
                if ( pmt == NULL )
                    exit(1);
                for (x = 0; x <= i; x++)
                    pmt[x] = string[x];
                arr[j] = pmt;
                i = 0;
                j += 1;
            }
            else
            {
                string[i] = c;
                i += 1;
            }
        }
    }
    for (i = 0; i <= j; i++)
        printf("%s\n", arr[i]);
    for(i = 0; i < ARR_SIZE; i++)
        free(arr[i]);
    free(pmt);
    return EXIT_SUCCESS;
}

Вывод правильный, но в конце выдает ошибку сегменирования:

abc  
d e f 
abc
def
Ошибка сегментирования (стек памяти сброшен на диск)

Ответы (1 шт):

Автор решения: AlexGlebe

Во первых у вас массив указателей char * arr [ ARR_SIZE ] ; содержит мусор памяти, и при удалении всего массива указателей происходит ошибка удаления памяти с неправильными адресами.
Цикл надо чуток укоротить до i < j , строго меньше:

for(i = 0; i < j; i++)
    free(arr[i]);

Во вторых, адрес pmt уже хранится в массиве arr и двойное удаление указателя приведёт опять к ошибке.
Убираем это :

// free(pmt);

И наконец правильные указатели хранятся по индексам 0 .. j-1, а вы выводите включительно, исправляем на i < j :

for (i = 0; i < j; i++)
    printf("%s\n", arr[i]);
→ Ссылка