Правильное использование malloc
Я пытаюсь поместить мой путь к каталогу в строковую переменную, например так:
int main(int ac, char **av)
{
char*dir;
if(ac > 2)
{
dir = malloc(sizeof(*dir) * 512);
getcwd(dir, sizeof(*dir));
printf("dat dir is:\n");
printf("%s\n", dir);
}
}
Я получил печатный бланк, но когда я делаю что-то подобное
int main(int ac, char **av)
{
char dir[512];
if(ac > 2)
{
// dir = malloc(sizeof(dir) * 512);
getcwd(dir, sizeof(dir));
printf("dat dir is:\n");
printf("%s\n", dir);
}
}
это напечатано правильно, почему? Разве мой первый malloc не предполагает превращение моей переменной в dir[512]
4 ответа
В
getcwd(dir, sizeof(*dir))
sizeof
производит 1, потому что *dir
относится к одному char
, Это не то, что вы хотите. Если вы замените это на 512, все должно работать нормально.
Идиоматическое кодирование будет примерно таким:
int main(int ac, char **av)
{
const int buf_size = 512;
char *dir;
if(ac > 2)
{
dir = malloc(buf_size);
getcwd(dir, buf_size);
printf("dat dir is:\n");
printf("%s\n", dir);
}
}
Примечание умножение на sizeof(*dir)
не работает, потому что он всегда возвращает 1. То есть malloc
выделяет в единицах char
, Так что я опустил no-op.
Это связано с массивами, указателями и значением sizeof
,
char dir[512];
sizeof(dir);
Это запрашивает размер массива, который в этом случае sizeof(char) * 512
-> 512
,
char *dir;
sizeof(dir);
Это запрашивает размер указателя, который в данном случае sizeof(char *)
-> 4
или же 8
char *dir;
sizeof(*dir);
Это странная конструкция. Я действительно не чувствую себя комфортно с этим. Так как dir
не было инициализировано разыменование dir
это повод для беспокойства. Но я думаю, что компилятор работает здесь правильно, что в данном случае sizeof(char)
-> 1
,
При работе с указателями, вы должны носить с собой размер, который вы выделили.
char*dir;
if(ac > 2)
{
dir = malloc(sizeof(char) * 512);
getcwd(dir, sizeof(char) * 512);
printf("dat dir is:\n");
printf("%s\n", dir);
}
Правильный ответ ™ немного сложнее.
if (ac > 2)
{
size_t size = 512;
char *buf = malloc(size);
char *dir = getcwd(buf, size);
while (dir == NULL && errno == ERANGE)
{
size *= 2;
buf = realloc(buf, size);
dir = getcwd(buf, size);
}
printf("dat dir is:\n");
printf("%s\n", dir);
free(buf);
}
Во-первых, я бросаю sizeof(char)
, В С, sizeof(char)
определяется как 1
так что это избыточно. Далее установите dir
в качестве возвращаемого значения getcwd(3)
и держите буфер данных отдельно. Обязательно проверьте возвращаемое значение, если getcwd(3)
возвращается NULL
а также errno
является ERANGE
затем buf
был недостаточно велик. В моем примере я удваиваю размер буфера перед попыткой getcwd(3)
снова. Наконец, не забудьте освободить buf
,
Здесь я не проверяю возвращаемое значение malloc(3)
или же realloc(3)
, Это потому, что я чувствую, что в этом примере нет смысла. Если я не могу определить размер пути, моя программа будет зависать независимо от того, что я делаю.
Всякий раз, когда вы динамически выделяете память, всегда проверяйте возвращаемое значение из calloc, malloca и realloc, поскольку возвращаемое значение указывает, что память выделена успешно или нет. Здесь вышеупомянутый первый ответ хорош, и проверить возвращаемое значение всегда полезно.
Меньше вещей, которые могут пойти не так, если вы поместите размер в переменную на ранней стадии, а затем используете это:
{ const sizeof_dir = sizeof (* dir) * 512; dir = malloc (sizeof_dir); getcwd (dir, sizeof_dir); printf ("dat dir is: \ n"); printf ("% s \ n", dir); }
Что убило тебя было getcwd(dir, sizeof(*dir))
где размер был еще 1.