Конкатенация строк и 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;
}

РЕДАКТИРОВАТЬ:

Обновленный код после прочтения некоторых ответов:

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;
}

РЕДАКТИРОВАТЬ:

Рабочий код:

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;
}

3 ответа

Решение

Проблема с вашей строкой формата:

sprintf(id, "%s%d", pid);

Ваша строка формата имеет два форматера (%s для строки и %d для int), но вы только проходите pid_t, Вы, вероятно, имеете в виду:

sprintf(id, "%s%d", hostname, pid);

или же

sprintf(id, "%d", pid);

В вашем коде %s интерпретирует pid в качестве указателя. Попытка разыменования того, что форматирование строки вызывает ошибку сегментации, так как это недопустимое значение указателя.

Проблема с управлением памятью:

Но в вашем коде также есть неопределенное поведение: вы объявляете 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);

Не знаю, где вы находитесь, но у вас есть несколько проблем.

snprintf () намного безопаснее и не будет переполнять буфер id[]. sprintf может переполнить буфер

sprintf(id, "%s%d", pid) неверен, как упомянуто выше.

return id неверен, так как возвращает указатель на значение в стеке. Как только вы вернетесь, стек больше не ваш.

sprintf(id, "%s%d", pid);

У вас есть два селектора%s и%d, но только один параметр (pid). Вам нужно вставить строку и целое число вместо целого числа.

Другие вопросы по тегам