LINUX.ORG.RU

инициализация char **buffer; и Valgrind

 , ,


0

2

как ининциализировать?

char **buffer;
buffer = malloc(15 * sizeof(char*) + 1); // Valgring ругается фразой Uninitialised value was created by a heap allocation
for (int i = 0; i < 15; i++){
    buffer[i] = malloc(20 + 1);

    printf("%s", buffer[i]); // Valgring ругается фразой  Use of uninitialised value of size 8
}

// Освобождаю память так
for (int i = 0; i < 15; i++)
    free(buffer[i]);
free(buffer);

★★★★★

Последнее исправление: sniper21 (всего исправлений: 2)
Ответ на: комментарий от unC0Rr

Да забыл указать что malloc делаю.

sniper21 ★★★★★
() автор топика

Прямо перед строкой, где второе предупреждение вываливается, нужно инициализировать *buffer[i]. Остальное, вроде, в порядке

Deleted
()

И это:

15
15
15

в константу/переменную запихнуть

Deleted
()

Ну выделил ты память, ничего туда не положил, и хочешь распечатать? Это UB, так делать нельзя.

pftBest ★★★★
()
malloc(15 * sizeof(char*) + 1)

Нахрена тебе память на 15 указателей и ещё один байт? Что ты с этим байтом делать собрался?

printf("%s", buffer[i]);

Ты мусор из юзанной памяти, печатать собрался, что-ли? Почисти хоть перед использованием и что-нибудь null-terminated туда запиши.

Stanson ★★★★★
()
Последнее исправление: Stanson (всего исправлений: 2)
Ответ на: комментарий от Stanson

Думал, надеялся что будет так: char **buffer = { {}, {}, {}, {}, NULL}

Типа указатель на указатель на строки завершенные NULL

sniper21 ★★★★★
() автор топика
Последнее исправление: sniper21 (всего исправлений: 1)

Утечек, кстати, нет.

А эффективно инициализировать так:

for (int i = 0; i < 15; i++){
    buffer[i] = malloc(20 + 1);

    memset(buffer[i], 0, 20+1); // инициализировать нулями

Причём, обнуление не всегда нужно. Здесь, например, только из-за того, что в массив нет никакой осмысленной записи определённого кол-ва элементов перед использованием информации об их кол-ве и их содержимого.

gag ★★★★★
()
Ответ на: комментарий от sniper21

Типа указатель на указатель на строки завершенные NULL

Ну так NULL это тоже указатель, и ему надо sizeof(char*) места, а ты ему байт всего выделяешь. Да ещё и не инициализируешь этим NULL.

Да и вообще, используй calloc вместо malloc, он хоть за тебя выделенную память обнулит, и не даст с размером вот таким смешным образом накосячить.

Stanson ★★★★★
()
Последнее исправление: Stanson (всего исправлений: 1)
Ответ на: комментарий от gag

В посте, на который я отвечал, нет указания, что buffer - это строка.

Эмм, как бы

printf("%s", buffer[i]);

ни о чём даже не намекает?

Stanson ★★★★★
()
Ответ на: комментарий от sniper21

Думал, надеялся что будет так: char **buffer = { {}, {}, {}, {}, NULL}

Так и сделай

buffer = malloc((EL_COUNT+1) * sizeof(char*));

Тогда и будет что ты описал. А так выходит у тебя. {p1<8или4байт>, p2<8или4байт>, 1 байт>

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

Dudraug ★★★★★
()
Ответ на: комментарий от Stanson

Намёк мог быть настолько же точным, как и тег «memory leak».

gag ★★★★★
()
Ответ на: комментарий от sniper21

Думал, надеялся что будет так: char **buffer = { {}, {}, {}, {}, NULL}

  const size_t N = 15;
  const size_t M = 20;
  char **buffer;
  char **p_str;
  size_t i;


  buffer = malloc((N + 1) * sizeof(char *));
  for (i = 0; i < N; i++) {
    buffer[i] = calloc(M + 1, sizeof(char));
    buffer[i][0] = '0' + (char)(i % 10);
  }
  buffer[N] = NULL;


  for (p_str = buffer; *p_str; ++p_str) {
    printf("%s\n", *p_str);
  }


  for (p_str = buffer; *p_str; ++p_str) {
    free(*p_str);
  }
  free(buffer);
AlexVR ★★★★★
()

кстати, если строки где-нить не реаллоцируются, то можно всё упихнуть в один calloc() - взять сразу всю нужную память.

char **alloc_strings(size_t n,size_t m) {
  char **buffer=(char **)calloc((n+1)*sizeof(char *)+n*(m+1));
  for(int t=0;t<n;t++) {
     buffer[t]=((char *)buffer)+(n+1)*sizeof(char *)+t*(m+1);
  }
  return buffer;
}

для строк приём конечно излишен, но для матриц самое то

MKuznetsov ★★★★★
()
Ответ на: комментарий от vzzo

как я понял ТС, у него используются NULL-терминатор и он передаёт размерности без учёта терминаторов.

MKuznetsov ★★★★★
()
Последнее исправление: MKuznetsov (всего исправлений: 1)
Ответ на: комментарий от sniper21

Если хочешь так - используй calloc, а не malloc

Aswed ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.