Безопасно ли передавать адрес указателя на символ, чтобы указать на локальную переменную массива - PullRequest
0 голосов
/ 24 апреля 2020

На самом деле в приведенной ниже программе я пытаюсь найти причину, передавая адрес указателя. Согласно концепции стека, локальные переменные в кадре стека уничтожаются при выполнении кадра. Поэтому мой вопрос заключается в том, как буфер [100], объявленный внутри функции, все еще доступен из main (). Я просто запутался. В любом случае я получил желаемый результат.

#include <stdio.h>
#include <string.h>

#define TCP_SYSLOG_MANUAL_BLOCK "TCP syslog manual blocking enabled"
#define TCP_SYSLOG_MSQ_QFULL "TCP syslog message Queue full"
#define TCP_SYSLOG_HOST_DOWN "TCP Syslog server is DOWN"

void get_server_unreach_reason(char **reason)
{
        char buffer[100];
        printf("start addr of Buffer : %p\n", buffer);

        strncpy(buffer, TCP_SYSLOG_MANUAL_BLOCK, strlen(TCP_SYSLOG_MANUAL_BLOCK));
        printf("Buffer : %s\n", buffer);

        strcat(buffer, ", ");
        strncat(buffer, TCP_SYSLOG_MSQ_QFULL, strlen(TCP_SYSLOG_MSQ_QFULL));
        printf("Buffer : %s\n", buffer);

        strcat(buffer, ", ");
        strncat(buffer, TCP_SYSLOG_HOST_DOWN, strlen(TCP_SYSLOG_HOST_DOWN));
        printf("Buffer : %s\n", buffer);

        *reason = buffer;
}
int main()
{
        char *reason;
        get_server_unreach_reason(&reason);
        printf("reason pointing addr : %p\n", reason);
        printf("reason : %s\n", reason);
        return 0;
}

Вывод:

[revarath@bgl-vms-vm0251 basic]$ ./a.out
start addr of Buffer : 0x7ffe4efb2780
Buffer : TCP syslog manual blocking enabled
Buffer : TCP syslog manual blocking enabled, TCP syslog message Queue full
Buffer : TCP syslog manual blocking enabled, TCP syslog message Queue full, TCP Syslog server is DOWN
reason pointing addr : 0x7ffe4efb2780
reason : TCP syslog manual blocking enabled, TCP syslog message Queue full, TCP Syslog server is DOWN

Хорошо, теперь я понял вашу точку зрения. Пожалуйста, предложите, что приведенный ниже код подходит.

void get_server_unreach_reason(char *buffer, int buflen)
{
        ....
        strncpy(buffer, TCP_SYSLOG_MANUAL_BLOCK, strlen(TCP_SYSLOG_MANUAL_BLOCK));
        printf("Buffer : %s\n", buffer);

}
int main()
{
        char reason[100];
        get_server_unreach_reason(reason, sizeof(reason));
        ....
}

Если все в порядке, у меня есть еще один вопрос. Предположим, что если мы вызываем get_server_unreach_reason () из разных мест (вызывающих), то во всех местоположениях вызывающих мы должны статически распределять буфер перед передачей в функцию.

Ответы [ 2 ]

2 голосов
/ 24 апреля 2020

Нет.

Указатель, возвращенный функцией, недействителен, поскольку память, на которую он указывает, больше не существует.

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

Вам нужно объявить локальную переменную <b>static</b> char buffer[100];, чтобы она работала, но Имейте в виду, что любой вызов функции будет возвращать тот же указатель.

0 голосов
/ 24 апреля 2020

«Пока кадр стека все еще там», ответом будет «да».

Но я буду первым, кто скажет, что вы не должны этого делать: ничто (!) Не является более ужасным для отладки, чем «что-то, что« чертит стек! »» Если вы хотите обойтись «указатель на что-то», пусть это «что-то» всегда (!) будет тем, что вы явно выделяете из кучи.

Конечно: «если это действительно однократный вызов функции, который собирается вызывать и приходить прямо сейчас, и ничто не собирается пытаться запомнить значение указателя, которое вы указали, "без проблем. Но - меня сжигали слишком много раз.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...