утечка памяти при манипуляциях с символами * - PullRequest
0 голосов
/ 29 сентября 2010

Я делаю что-то подобное в цикле:

char* test = "\0";

test = strcat(test, somestr);
...
char* tmp = strstr(test, 0, len);

free(test);
test = tmp;

и получаем утечку памяти.Что я делаю не так?

Ответы [ 3 ]

3 голосов
/ 29 сентября 2010

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

char* test = "\0";

Это объявляет указатель с именем test и инициализирует его, чтобы указывать на некоторый буквенный массив из двух байтов {0, 0}

test = strcat(test, somestr);

Это пытается что-то добавить к концу этого строкового литерала (и, поскольку строка C пуста, она будет похожа на строковую копию). Литеральные значения часто хранятся в памяти, которая недоступна для записи, поэтому копирование чего-либо в эту память может вызвать ошибку (ошибка сегментации или SIGSEGV во многих операционных системах). Кроме того, у вас есть только два байта памяти, на которые указывает test , что означает, что если somestr не ссылается на строку, чья strlen меньше или равна 1, то вы в конечном итоге попытается перезаписать какую-то другую память (что будет после «\ 0», на которое указывает test ).

char* tmp = strstr(test, 0, len);

Я не знаю, что здесь происходит, поскольку strstr принимает только 2 аргумента (оба const char *).

free(test);

Здесь вы пытаетесь освободить память, выделенную без кучи. Куча - это то, где malloc, realloc и calloc получают память, которую они выделяют. Вызов free с областью памяти, которая не была возвращена одной из этих функций (и некоторыми другими функциями в некоторых системах), является ошибкой, поскольку free не знает, что с ними делать .

Вам, вероятно, следует иметь в виду, что часто память представляет собой огромный массив байтов, а используемые вами указатели похожи на индексы массивов. Система, которую вы используете, может различать некоторые области этого массива и определять, как вы можете получить к ним доступ (читаемый, записываемый и / или исполняемый). Но это все еще просто массив байтов. Если у вас есть строка (например, "foo"), это означает, что где-то в ОЗУ есть четыре байта (3 буквы + байт терминатора \ 0), и вы можете получить доступ к этой области, зная ее индекс в массиве байтов, который является ОЗУ , Скорее всего, рядом с вашей строкой хранятся другие вещи (например, { ..., 4, 2, 'f', 'o', 'o', 0, 99, 3, 2, ...}), поэтому вы должны убедиться, что вы остаетесь в пространстве этой памяти, не забираясь в смежные данные.

1 голос
/ 29 сентября 2010

Вы не можете strcat до test, потому что вы изначально указываете на постоянную char * Вам нужно выделить память для этого. strcat не сделает этого.

Измените свой код на что-то вроде:

char* test = (char*)malloc(20*sizeof(char));
test[0] = '\0'; // nothing on this string to begin with
strcat(test, "something");
free(test);

Кроме того, это не будет работать:

char* tmp = strcat(test, 0, len);

Поскольку отсутствует функция strcat с тремя параметрами.

Помните. В 99,9% случаев будет free звонок для каждого malloc распределения.

1 голос
/ 29 сентября 2010

Есть несколько проблем:

  1. strcat добавит строку в буфер назначения. Первый параметр должен быть буфером, а не строковым литералом-указателем. Вот пример буфера символов или также называется массивом символов: char test[1024];

  2. Возвращаемое значение strcat - это указатель на буфер назначения, а не вновь выделенная строка в куче. Поэтому не следует вызывать free для возвращаемого значения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...