Проблемы с динамическим выделением памяти для структур в C - PullRequest
0 голосов
/ 12 декабря 2018

Мне дали неизвестное количество "широких символов".Текст форматируется как предложения, которые я должен добавить в структуру «Текст».

Это мои структуры:

struct Sentence {
    wchar_t *sentence;
    int amount_of_symbols;
};

struct Text {
    struct Sentence *sentences;
    int amount_of_sentences;
}; 

Я динамически выделяю память для массива структур «Предложение» идобавь их.Это мой входной код:

int amount_of_sentences = 0;
struct Sentence *sentences = (struct Sentence *) malloc(amount_of_sentences * sizeof(struct Sentence));

struct Text text = {sentences, amount_of_sentences};

wchar_t symbol;
int buffer_size = 0;
wchar_t *buffer = (wchar_t *) malloc(buffer_size * sizeof(wchar_t));

bool sentence_begun = true;

while (true) {
    symbol = getwchar();

    if (symbol == '\n')
        break;

    if (sentence_begun && symbol == ' ') {
        sentence_begun = false;
        continue;
    }

    buffer = (wchar_t *) realloc(buffer, (++buffer_size) * sizeof(wchar_t));
    buffer[buffer_size - 1] = symbol;

    if (symbol == '.') {
        buffer[buffer_size] = '\0';

        text.amount_of_sentences++;
        text.sentences = (struct Sentence *) realloc(text.sentences, text.amount_of_sentences * sizeof(struct Sentence));
        text.sentences[text.amount_of_sentences - 1].amount_of_symbols = buffer_size;
        text.sentences[text.amount_of_sentences - 1].sentence = (wchar_t *) malloc(buffer_size * sizeof(wchar_t));
        text.sentences[text.amount_of_sentences - 1].sentence = buffer;

        buffer_size = 0;
        buffer = (wchar_t *) realloc(buffer, buffer_size * sizeof(wchar_t));
        sentence_begun = true;
    }
}

Кажется, все в порядке, но как только я пытаюсь вывести все свои предложения, отображаются не все, а некоторые повторяются.

Это мой код вывода:

for (int i = 0; i < text.amount_of_sentences; i++) {
    wprintf(L"%ls\n", text.sentences[i].sentence);
}

Пример ввода-вывода:

adjsand. asdad.a.a. aaaa. adsa.


a.

adsa.
adsa.

Что может быть не так с этим кодом и что я должен изменить?

Ответы [ 2 ]

0 голосов
/ 12 декабря 2018

Проблема здесь.

    text.sentences[text.amount_of_sentences - 1].sentence = (wchar_t *) malloc(buffer_size * sizeof(wchar_t));
    text.sentences[text.amount_of_sentences - 1].sentence = buffer;

    buffer_size = 0;
    buffer = (wchar_t *) realloc(buffer, buffer_size * sizeof(wchar_t));

Вы выделяете новое предложение с помощью malloc, а затем перезаписываете его с помощью buffer.Это приведет к утечке памяти.

Затем вы назначаете buffer на text.sentences[text.amount_of_sentences - 1].sentence, а затем освобождаете эту память путем перераспределения buffer.

Из стандарта C ...

Функция realloc освобождает старый объект, на который указывает ptr , и возвращает указатель на новый объект, размер которого указан в размере.

text.sentences[text.amount_of_sentences - 1].sentence указывает на свободную память.Это приведет к неопределенному поведению.

Вместо этого укажите на buffer и выделите новое buffer.

    text.sentences[text.amount_of_sentences - 1].sentence = buffer;

    buffer_size = 0;
    buffer = malloc(buffer_size * sizeof(wchar_t));

Некоторые другие примечания ...

Как отметил Пол , вам нужно выделить дополнительный байт для нулевого байта.

Нет необходимости приводить результат к malloc или realloc.

Проще, быстрее и менее подвержено ошибкам выделять большой буфер в стеке для чтения входных данных (увеличивая их при необходимости).Затем скопируйте содержимое в память соответствующего размера.

Я продолжил и кодировал улучшенную версию для иллюстрации.Если это домашнее задание, не сдавайте его.

0 голосов
/ 12 декабря 2018

Во-первых, ваш буфер на 1 слишком мал и не учитывает завершающую '\0'.В верхней части вашей программы выполните:

int buffer_size = 1;
wchar_t *buffer = (wchar_t *) malloc(buffer_size * sizeof(wchar_t));
*buffer= '\0';

Но реальная проблема заключается в:

    text.sentences[text.amount_of_sentences - 1].sentence =
                (wchar_t *) malloc(buffer_size * sizeof(wchar_t));
    text.sentences[text.amount_of_sentences - 1].sentence = buffer;

    buffer_size = 0;
    buffer = (wchar_t *) realloc(buffer, buffer_size * sizeof(wchar_t));

Вы выделяете память для предложения, но затем перезаписываете этот указатель с помощью *Указатель 1008 *.Затем вы сбрасываете размер буфера и перераспределяете буфер.

Назначение не копирует данные буфера.Для этого выполните:

    strcpy(text.sentences[text.amount_of_sentences - 1].sentence, buffer);

и здесь тоже:

buffer_size = 1;
buffer = (wchar_t *) realloc(buffer, buffer_size * sizeof(wchar_t));
*buffer= '\0';
...