Я изучаю 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.
Что я делаю не так?
Все ваши &s[i]
должны быть просто s[i]
. &s[i]
имеет тип char **
, поэтому его нельзя использовать с scanf
, printf
и т. д. s[i]
имеет тип char *
, что вам и нужно. Ваш компилятор должен был предупредить об этих ошибках. На практике указатели будут иметь одинаковое значение, так что "работает", но это неправильно.
М. Оэм прав, хотя, если вы хотите сохранить свою строку по определенному индексу, вы можете использовать scanf('%s",&s[i][index]
, scanf("%s",s[i])
эквивалентно scanf("%s",&s[i][0]
.
Примечание: 3221226356 — это 0xC000 0374.
Лучший первый шаг — включить; все предупреждения компилятора. Хороший компилятор предупредит о scanf("%s", &s[i]); ... printf("%s - %d\n", &s[i], strlen(&s[i]));
и ускорит ваше программирование.
Все говорят, что мой сканф неверен. Как мне тогда получить пользовательский ввод? Должен ли я создать временную переменную и выполнить ее strcpy? Но не по этой ли причине прерываются звонки на free?
И это, похоже, сработало. Но теперь у меня другой вопрос, не будет ли у меня в конце неосвобожденной памяти? Malloc, который я вызываю на tmp? Или это освобождается, когда я вызываю free(s[i]) ?
Так что похвалы по поводу &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;
}
Ваши вызовы
malloc
иfree
выглядят нормально, но вы искажаете указатели на строки, вводяscanf
в&s[i]
вместоs[i]
. (Формат%s
и его двоюродный брат%[
берут строки для заполнения, которые уже переданы в качестве указателей. Также: пожалуйста, активируйте предупреждения с помощью-Wall
. Они покажут вам несоответствия формата.)