Ошибка: «указатель, являющийся realloc'd не был выделен» в macOS, но работает в Windows при попытке дважды перераспределить - PullRequest
0 голосов
/ 04 октября 2018

Я пытаюсь реализовать функцию, которая объединяет две строки, но я продолжаю получать ту же ошибку.msgstr "указатель, являющийся realloc'd, не был выделен" Когда я скомпилировал тот же код на машине с Windows, это сработало, я что-то упустил?Код ниже в основном то, что я пытаюсь сделать.main:

int main() {

int length = 4096;
char *string = malloc(length * sizeof(char));
createString(string, length);
realloc(string, 30);
return 0;
}

createString:

void createString(char * string, int length) {
  char *copyAdress = string;
  char *temp ="";
  int counter2 = 0;

  fflush(stdin);
  fgets(string, length,stdin);
  while(*string != EOF && *string != *temp ) {
    string++;
    counter++;
  }
  string = copyAdress;
  realloc(string, (counter)*sizeof(char));
}

Спасибо!Редактировать: я хочу, чтобы createString изменил размер строки на длину строки, которую я получаю с помощью fgets, имея тот же адрес, что и строка, которую я отправил, чтобы я мог выделить для нее больше памяти позже, когда захочу добавитьдругая строка к нему.

Ответы [ 4 ]

0 голосов
/ 04 октября 2018

Смотрите ответы других о том, что вы делаете неправильно.Однако сообщение об ошибке означает, что в MacOS realloc в createString освободил оригинал string и выделил новый, и теперь ваш realloc в main пытается realloc указатель, который недольше действующий (выделенный).В Windows память не была освобождена в createString, поэтому второй вызов reallocmain) получает действительный указатель.

0 голосов
/ 04 октября 2018

Если у вас realloc какая-то память, указатель, указывающий на исходную память, становится недействительным (если realloc не удалось и не вернул NULL).Поэтому двойной вызов realloc для одного и того же указателя действительно не должен работать (если он не вернул NULL в первый раз).

0 голосов
/ 04 октября 2018

Давайте разберемся с этим в порядке выполнения.

fflush(stdin); - это неопределенное поведение .Если вам действительно нужно очистить все в stdin, вы должны найти другой путь (например, цикл).Существуют компиляторы / системы с определенной реализацией, но я бы не стал на это рассчитывать.

string++; излишне, поскольку вы перезаписываете string после цикла.

realloc(string, (counter)*sizeof(char));

должно быть

char *temp = realloc(string, (counter)*sizeof(char));
if (temp != NULL)
  string = temp;

Таким образом, вы получите указатель, где находится ваш новый string, но я предлагаю вам прочитать ссылку на realloc.По сути, вы не знаете, был ли он перемещен, и старый адрес может быть недействительным с этого момента.Так что разыменование это также неопределенное поведение.

После этого вам придется вернуть новый адрес string или передать адрес указателя вашей функции.

Та же проблема повторяется свторой realloc.Вы только узнали, что ваш первый звонок был неправильным, потому что второй звонок заметил, что у вас нет действительных данных в том, что, по вашему мнению, будет вашим string.


Что касается вашего комментария:невозможно использовать realloc и быть уверенным, что перераспределенная память находится в том же месте, что и раньше.

0 голосов
/ 04 октября 2018

Существует несколько проблем:

  1. realloc(string, (counter)*sizeof(char)); неверно, вам нужно string = realloc(string, (counter)*sizeof(char));, потому что realloc может вернуть другой адрес.

  2. Вызов createString(string, length); не изменится string

Если вы хотите получить более точный ответ, вам нужно сообщить нам, что именно точно createString предполагается сделать.В вашем коде нет попытки объединить две строки.

...