Я был немного смущен концепцией указателей на символы, поэтому я сделал простой код, просто печатая свое имя, предоставленное пользователем (мной). Я также хотел попрактиковать 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;
}
0
jasson 1 Сен 2017 в 14:00

6 ответов

Лучший ответ

Память выделяется при утверждении:
strings = get_string();

Вам не нужно malloc это (char *strings = malloc(sizeof(char) * 10); )

Без malloc все будет работать нормально

0
S.I.J 19 Июн 2020 в 17:52

Строка 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() хуже, потому что он никогда не возвращает выделенные данные, но никогда не использует их повторно и приводит к прямой утечке памяти.

Код должен либо:

  1. Соответствуйте документации и требуйте от потребителя кода free() строки (для ясности, возможно, переименуйте ее, скажем, get_string_alloc()).
  2. Предложить библиотечную процедуру для освобождения строки (get_new_string() и release_string())

Не очень хороший способ изменить владение выделенной памятью в C, но удержание ее до конца выполнения определенно не ответ. Многие библиотеки ходят по домам, чтобы перенести распределение на потребительский код, но это обременительно, когда полный размер требуемого пространства не может быть известен, например, здесь.

Я бы предложил поместить _alloc() в конец любой функции, которая возвращает объекты, которые потребительский код должен позже free().

Таким образом, ответ на поставленный вопрос - удалить malloc() и free(), потому что библиотека обрабатывает оба. Однако будьте осторожны, если ваша программа выполняет много вызовов этой функции и других, которые внутренне полагаются на нее (например, get_double()), у вас может не хватить памяти, потому что библиотека находится в мертвом пространстве.

6
Persixty 2 Сен 2017 в 08:57

Сначала вы создали динамическую память, на которую будут указывать * строки . Но затем вы указываете на локальную строку (из функции 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;
}
0
Eswaran Pandi 1 Сен 2017 в 11:12

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;
    }
0
user6385115user6385115 1 Сен 2017 в 11:46

Проблема в том, что ваш get_strings переопределяет ваш начальный malloc. Значение указателя является значением. Приравнивая его к чему-то другому, вы заменили ваше значение malloc.

2
Michel Donais 1 Сен 2017 в 11:04

Вы не включаете код для 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);
}

Это довольно запутанно, но вы поняли идею.

0
unwind 1 Сен 2017 в 11:12