Я был немного смущен концепцией указателей на символы, поэтому я сделал простой код, просто печатая свое имя, предоставленное пользователем (мной). Я также хотел попрактиковать malloc, поэтому я сослался на указатель на определенную память в ОЗУ, но я действительно не знал, что ставить после «sizeof (char) *», потому что это пользовательский ввод, который еще не решен. Кроме того, после этого я освободил память, но в командной строке я получил сообщение об ошибке:
*** Error in `./char': double free or corruption (fasttop): 0x00000000017fe030 ***
Aborted
Кажется, что я освободил одну и ту же память дважды или что-то, но я не знаю, что удалить или добавить. Пожалуйста помоги!
#include <stdio.h>
#include <cs50.h>
int main (void)
{
char *strings = malloc(sizeof(char) * 10);
printf("What is your name?\n");
//wait for use to type his/her name
strings = get_string();
printf("Hello %s\n", strings);
free (strings);
return 0;
}
6 ответов
Память выделяется при утверждении:
strings = get_string();
Вам не нужно malloc
это (char *strings = malloc(sizeof(char) * 10);
)
Без malloc
все будет работать нормально
Строка strings = get_string();
фактически присваивает значение, возвращаемое get_string()
, strings
. Он не записывает это в выделенную вами память.
Таким образом, значение, возвращаемое malloc()
, было перезаписано (и в этом случае потеряно).
free(strings)
освобождает то, что get_string()
вернул. Вопрос не предоставляет код для этого, но, вероятно, он free()
недопустим.
Поскольку среда выполнения сообщала вам, что она была освобождена дважды, я предполагаю, что вы выделили память в get_string()
, затем освободили ее и вернули неверный указатель.
Если вы хотите использовать выделенную память, вам нужно изменить get_string()
, чтобы принять указатель:
void get_string(char *str){
//Do whatever writing you value into str[] as an array of char..
}
Хорошая практика будет иметь:
void get_string(char *str, size_t max){
//Do whatever writing you value into str[] as an array of char..
//Use max to avoid writing beyond the end of the space allocated...
}
Тогда звоните как get_string(strings,10);
.
РЕДАКТИРОВАТЬ: После небольшого исследования был выявлен недостаток. get_string()
напрямую не free()
возвращает строку, которую он возвращает, но добавляет ее в список выделений, сделанных библиотекой, которые освобождаются при выходе (в функции с именем teardown()
, зарегистрированной в {{X3) }} или другие функции, зависящие от компилятора).
Это плохой дизайн, потому что потребительский код не обеспечивает безопасного способа освобождения памяти, который в типичном случае использования не потребуется для выполнения всего приложения. get_double()
хуже, потому что он никогда не возвращает выделенные данные, но никогда не использует их повторно и приводит к прямой утечке памяти.
Код должен либо:
- Соответствуйте документации и требуйте от потребителя кода
free()
строки (для ясности, возможно, переименуйте ее, скажем,get_string_alloc()
). - Предложить библиотечную процедуру для освобождения строки (
get_new_string()
иrelease_string()
)
Не очень хороший способ изменить владение выделенной памятью в C, но удержание ее до конца выполнения определенно не ответ. Многие библиотеки ходят по домам, чтобы перенести распределение на потребительский код, но это обременительно, когда полный размер требуемого пространства не может быть известен, например, здесь.
Я бы предложил поместить _alloc()
в конец любой функции, которая возвращает объекты, которые потребительский код должен позже free()
.
Таким образом, ответ на поставленный вопрос - удалить malloc()
и free()
, потому что библиотека обрабатывает оба. Однако будьте осторожны, если ваша программа выполняет много вызовов этой функции и других, которые внутренне полагаются на нее (например, get_double()
), у вас может не хватить памяти, потому что библиотека находится в мертвом пространстве.
Сначала вы создали динамическую память, на которую будут указывать * строки . Но затем вы указываете на локальную строку (из функции get_string ()), используя указатель * strings . когда вы вызываете free, программа пытается удалить локальную (стековую) ссылку и выдает ошибку.
Чтобы решить эту ошибку, программа должна быть
#include <stdio.h>
#include <cs50.h>
int main (void)
{
char *strings = malloc(sizeof(char) * 10);
printf("What is your name?\n");
//wait for use to type his/her name
strcpy(strings, get_string()); // Use strcpy instead of assigning
printf("Hello %s\n", strings);
free (strings);
return 0;
}
char *strings;
- Нет необходимости в новом malloc, так как строка, возвращенная функцией get_string (), уже находится в куче, вам просто нужно подобрать указатель на первый символ. (ссылка на функцию get_string ())
Strings = get_string ();
Printf ("Hello% s \ n", строки);
- После печати строки вы должны освободить память, выделенную для нее, как указано в ссылке на функцию get_string ()
Сохраняет строку в куче (через malloc); память должна быть освобождена вызывающей стороной, чтобы избежать утечки.
Я думаю, что все остальное в порядке, попробуйте этот код:
#include <stdio.h>
#include <cs50.h>
int main (void)
{
char *strings;
printf("What is your name?\n");
//wait for use to type his/her name
strings = get_string();
printf("Hello %s\n", strings);
free (strings);
return 0;
}
Проблема в том, что ваш get_strings
переопределяет ваш начальный malloc
. Значение указателя является значением. Приравнивая его к чему-то другому, вы заменили ваше значение malloc
.
Вы не включаете код для get_string()
, но вы перезаписываете strings
его возвращаемым значением, которое неверно. Адрес, который вы передаете free()
, должен быть получен от malloc()
, и, похоже, вы его нарушаете (в дополнение к потере исходного возвращенного адреса для ваших 10 байтов).
Предполагая, что get_string()
возвращает статическое хранилище (то есть вам не нужно его освобождать), вы можете сделать это без участия malloc()
.
Если вы действительно хотите , это может сработать:
printf("What is your name?\n");
const char *name = get_string();
const size_t nlen = strlen(name);
char * const name_copy = malloc(nlen + 1);
if(name_copy != NULL)
{
memcpy(name_copy, name, nlen + 1);
printf("Hello %s (from my own memory!)\n", name_copy);
free(name_copy);
}
Это довольно запутанно, но вы поняли идею.
Похожие вопросы
Новые вопросы
c
C - это язык программирования общего назначения, используемый для системного программирования (ОС и встраиваемых), библиотек, игр и кроссплатформенности. Этот тег следует использовать с общими вопросами, касающимися языка C, как это определено в стандарте ISO 9899 (последняя версия 9899: 2018, если не указано иное, а также для запросов, специфичных для версии, с c89, c99, c11 и т. Д.). C отличается от C ++ и не должен сочетаться с тэгом C ++ без разумной причины.