Конкатенация строки и 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). Вам нужно поместить строку и целое число вместо целого числа.