Malloc () ошибка повреждения памяти после конкатенации строки - PullRequest
0 голосов
/ 28 апреля 2011

Ребята, я генерирую строку, которая представляет путь к файлу, объединяя макрос и строку.Функция такова:

char *userPath(char *username)
{
   char *path = (char*)malloc(sizeof(char) * (strlen(MAILBOXES) + strlen(username) + 1));
   path[0] = '\0';
   strcat(path, MAILBOXES);
   strcat(path, "/");
   strcat(path, username);
   return path;
}

Возвращенный указатель ссылается на правильную строку, но после некоторого вызова этой функции процесс выбрасывает очень и очень плохой * обнаруженный glibc ./ mmboxd: malloc (): повреждение памяти: 0x085310a8 ** с относительной обратной трассировкой.Я знаю, что здесь проблема, поскольку я однажды реализовал эту ошибку, а также потому, что здесь используется только один malloc.Что не так с этим фрагментом кода?

Ответы [ 8 ]

9 голосов
/ 28 апреля 2011

+1 должно быть +2, чтобы учесть добавляемый разделитель и нулевой терминатор. И вы можете опустить sizeof (char), который всегда будет 1.

4 голосов
/ 28 апреля 2011

Вот проблема:

   char *path = (char*)malloc(sizeof(char) * (strlen(MAILBOXES) + strlen(username) + 1));

Вы выделяете достаточно памяти для а) всех символов в MAILBOXES, б) всех символов в username и в) '/'персонаж, но вы забыли г) завершающий символ '\0'!Так что + 1 должно быть + 2

Есть несколько других странностей в вашем коде, но они не ошибаются, только вещи, которые могут быть лучше:

  1. Вы понимаетене нужно приводить возвращаемое значение malloc в C, и некоторые (как я) считают это плохим стилем по различным причинам, по которым вы более чем способны к поиску в Google.
  2. sizeof(char) всегда равен 1(это определено в стандарте).Некоторые люди говорят, чтобы сохранить это для симметрии.Некоторые говорят, что убери это, так как это один.Некоторые говорят, что измените его на sizeof *path, так что если вы измените path на wchar_t *, malloc будет корректно корректироваться, чтобы продолжать выделять правильный размер.
  3. Использование strcat для записи первогобит данных в строку потенциально неэффективен.Почему бы не отбросить строку path[0] = '\0'; и просто использовать strcpy для первого бита данных?
  4. Вы вычисляете длины всех строк, но затем вы отбрасываете их и используете strcat, чтобудет пересекать (рассчитанные ранее) длины, чтобы найти правильное место.Если вы сохранили результаты ваших двух вызовов strlen, вам не нужно было бы использовать strcat и без необходимости продолжать пересчитывать, где находится конец строки.
  5. Использование strcat для добавления одного символанеэффективно.
  6. Вы не проверяете возвращаемое значение malloc на успех или неудачу, прежде чем использовать его.
2 голосов
/ 28 апреля 2011

Похоже, у вас нет места для нулевого терминатора. Вы должны выделить для этого дополнительно char.

Я предполагаю, что +1 в malloc() для разделителя пути. Сделайте это +2, и у вас будет место для завершающего нулевого символа.

1 голос
/ 28 апреля 2011

Ваш +1 в конце malloc() составляет /.Но вам нужно место для нулевого символа в конце, который добавляется strcat().Так что это +2.

char *path = (char*)malloc(sizeof(char) * (strlen(MAILBOXES) + strlen(username) + 2));
1 голос
/ 28 апреля 2011

Вы не планируете использовать char для завершающего нуля.Длина вашего malloc должна быть +2, а не +1.

1 голос
/ 28 апреля 2011

Вам необходимо выделить один дополнительный байт для нулевого символа "\ x00" в качестве ограничителя строки в строках C.

В настоящее время вы выделяете только один дополнительный байт для символа /.

Так что попробуйте+2 вместо + 1

1 голос
/ 28 апреля 2011

Похоже, вам понадобится переместить другой байт для нулевого завершения.

1 голос
/ 28 апреля 2011

Когда вы выделяете строку «path», вы забыли добавить длину символа «/», который вы добавляете между MAILBOXES и именем пользователя.

...