Конкатенация строки и int приводит к ошибке сегментации в C
Я не уверен, что я делаю неправильно.
Я пытаюсь объединить hostname
с помощью pid
, чтобы создать id
.
char *generate_id(void) {
int ret;
char id[1048];
char hostname[1024];
pid_t pid = getpid();
//hostname[1023] = '\0';
if ((ret = gethostname(hostname,1024) < 0)) {
perror("gethostname");
exit(EXIT_FAILURE);
}
sprintf(id, "%s%d", pid);
printf("hostname is %s\n", hostname);
printf("The process id is %d\n", pid);
printf("The unique id is %s", id);
return id;
}
EDIT:
Обновлен код после чтения некоторых ответов:
char *generate_id(void) {
int ret;
char hostname[1024];
pid_t pid = getpid();
//hostname[1023] = '\0';
if ((ret = gethostname(hostname,1024) < 0)) {
perror("gethostname");
exit(EXIT_FAILURE);
}
int size = snprintf(NULL, 0, "%s%d", hostname, pid);
char * id = malloc(size + 1);
printf("hostname is %s\n", hostname);
printf("The process id is %d\n", pid);
printf("The unique id is %s\n", id);
return id;
}
EDIT:
Рабочий код:
char *generate_id(void) {
int ret;
char hostname[1024];
pid_t pid = getpid();
//hostname[1023] = '\0';
if ((ret = gethostname(hostname,1024) < 0)) {
perror("gethostname");
exit(EXIT_FAILURE);
}
int size = snprintf(NULL, 0, "%s%d", hostname, pid);
char * id = malloc(size + 1);
sprintf(id, "%s%d", hostname, pid);
printf("hostname is %s\n", hostname);
printf("The process id is %d\n", pid);
printf("The unique id is %s\n", id);
return id;
}
Ответы
Ответ 1
Проблема с вашей строкой формата:
sprintf(id, "%s%d", pid);
Ваша строка формата содержит два форматирования (%s
для строки и %d
для int
), но вы передаете только pid_t
. Вероятно, вы имеете в виду:
sprintf(id, "%s%d", hostname, pid);
или
sprintf(id, "%d", pid);
В вашем коде %s
интерпретирует pid
как указатель. Попытка разыменовать, что для форматирования строки вызывает ошибку сегментации, так как это недопустимое значение указателя.
Проблема с управлением памятью:
Но тогда в коде есть также undefined поведение: вы объявляете id
как выделенный стек, но вы возвращаете этот массив (который распадается на указатель здесь). Это также неверно и может привести к краху позже.
Вам нужно изменить id
на массив, выделенный массивом:
char * id = malloc(1024);
Абонент вашей функции generate_id
затем должен free
сохранить память.
Вероятно, неплохо выделить только пространство, в котором вы нуждаетесь. Вы можете использовать snprintf
для этого:
// Determine how much space the string needs.
int size = snprintf(NULL, 0, "%d", pid);
// Allocate the required space plus NULL termination.
char * id = malloc(size + 1);
// Actually print the string.
sprintf(id, "%d", pid);
Ответ 2
Не уверен, где вы сталкиваетесь, но у вас есть несколько проблем.
snprintf() намного безопаснее и не будет превышать буфер id []. sprintf может перехватить буфер
sprintf (id, "% s% d", pid) плохо, как указано выше.
return id плохо, поскольку возвращает указатель на значение в стеке. Как только вы вернетесь, стек больше не будет вашим.
Ответ 3
sprintf(id, "%s%d", pid);
У вас есть два селектора% s и% d, но только один параметр (pid). Вам нужно поместить строку и целое число вместо целого числа.