Почему я получаю сообщение об ошибке 3221226356 при бесплатном вызове в C?

Я изучаю C и выполняю некоторые задачи по программированию, чтобы научиться.
При выполнении 1 задачи мне нужно создать динамический массив 2D-символов.

Я пытаюсь следовать некоторым другим ответам StackOverflow, чтобы динамически создавать 2D-массив.

У меня получается его создать, но при попытке освободить память получаю ошибку 3221226356.
Ниже мой код:

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

    int main(int argc, char *argv[])
    {
        int n;
        scanf("%d", &n);

        char **s = malloc(n * sizeof(char *));

        for (int i = 0; i < n; i++)
        {
            s[i] = malloc(1000 * sizeof(char));
            //memset(s[i], '\0', 1000);
            scanf("%s", &s[i]);
        }

        for (int i = 0; i < n; i++)
        {
            printf("%s - %d\n", &s[i], strlen(&s[i]));
        }

        for (int i = 0; i < n; i++)
        {
            printf("Freeing %d\n", i);
            //char *tmp = &s[i];
            free(s[i]);
        }

        printf("Freeing s\n");

        free(s);

        if (argc > 1)
        {
            char xx[100];
            scanf("%s", xx);
        }
        return EXIT_SUCCESS;
    }

И пример запуска кода с выводом:

2
xx
sss
xx - 2
sss - 3
Freeing 0

[process exited with code 3221226356]

Я пробовал вызывать free для &s[i], а также для *s[i], но оба результата приводят к ошибке.
Мой компилятор - GCC.

Что я делаю не так?

Ваши вызовы malloc и free выглядят нормально, но вы искажаете указатели на строки, вводя scanf в &s[i] вместо s[i]. (Формат %s и его двоюродный брат %[ берут строки для заполнения, которые уже переданы в качестве указателей. Также: пожалуйста, активируйте предупреждения с помощью -Wall. Они покажут вам несоответствия формата.)

M Oehm 13.12.2020 20:40

Все ваши &s[i] должны быть просто s[i]. &s[i] имеет тип char **, поэтому его нельзя использовать с scanf, printf и т. д. s[i] имеет тип char *, что вам и нужно. Ваш компилятор должен был предупредить об этих ошибках. На практике указатели будут иметь одинаковое значение, так что "работает", но это неправильно.

Tom Karzes 13.12.2020 21:02

М. Оэм прав, хотя, если вы хотите сохранить свою строку по определенному индексу, вы можете использовать scanf('%s",&s[i][index] , scanf("%s",s[i]) эквивалентно scanf("%s",&s[i][0] .

alex01011 13.12.2020 21:50

Примечание: 3221226356 — это 0xC000 0374.

chux - Reinstate Monica 13.12.2020 22:56

Лучший первый шаг — включить; все предупреждения компилятора. Хороший компилятор предупредит о scanf("%s", &s[i]); ... printf("%s - %d\n", &s[i], strlen(&s[i])); и ускорит ваше программирование.

chux - Reinstate Monica 13.12.2020 23:01

Все говорят, что мой сканф неверен. Как мне тогда получить пользовательский ввод? Должен ли я создать временную переменную и выполнить ее strcpy? Но не по этой ли причине прерываются звонки на free?

Quintonn 15.12.2020 17:53

И это, похоже, сработало. Но теперь у меня другой вопрос, не будет ли у меня в конце неосвобожденной памяти? Malloc, который я вызываю на tmp? Или это освобождается, когда я вызываю free(s[i]) ?

Quintonn 15.12.2020 18:28
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
7
137
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Так что похвалы по поводу &s[i] привели меня к очевидному решению.
Чтобы создать временную переменную для scanf.

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

int main(int argc, char *argv[])
{
    int n;
    scanf("%d", &n);

    char **s = malloc(n * sizeof(char *));

    for (int i = 0; i < n; i++)
    {
        //s[i] = malloc(1000 * sizeof(char));
        char *tmp = malloc(sizeof(char));
        //memset(s[i], '\0', 1000);
        scanf("%s", tmp);
        s[i] = tmp;
    }

    for (int i = 0; i < n; i++)
    {
        printf("%s - %d\n", s[i], strlen(s[i]));
    }

    for (int i = 0; i < n; i++)
    {
        printf("Freeing %d\n", i);
        //char *tmp = &s[i];
        free(s[i]);
    }

    printf("Freeing s\n");

    free(s);

    if (argc > 1)
    {
        char xx[100];
        scanf("%s", xx);
    }
    return EXIT_SUCCESS;
}

Другие вопросы по теме