Безопасен ли этот указатель? - PullRequest
0 голосов
/ 12 июня 2019

Несколько дней назад я хотел найти безопасную альтернативу atoi и нашел следующий код в ответ на этот ТАК вопрос:

#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>

typedef enum {
    STR2INT_SUCCESS,
    STR2INT_OVERFLOW,
    STR2INT_UNDERFLOW,
    STR2INT_INCONVERTIBLE
} str2int_errno;

str2int_errno str2int(int *out, char *s, int base) {
    char *end;
    if (s[0] == '\0' || isspace(s[0]))
        return STR2INT_INCONVERTIBLE;
    errno = 0;
    long l = strtol(s, &end, base);
    /* Both checks are needed because INT_MAX == LONG_MAX is possible. */
    if (l > INT_MAX || (errno == ERANGE && l == LONG_MAX))
        return STR2INT_OVERFLOW;
    if (l < INT_MIN || (errno == ERANGE && l == LONG_MIN))
        return STR2INT_UNDERFLOW;
    if (*end != '\0')
        return STR2INT_INCONVERTIBLE;
    *out = l;
    return STR2INT_SUCCESS;
}


int main(void) {
  int i;
    /* Lazy to calculate this size properly. */
    char s[256];

    /* Simple case. */
    assert(str2int(&i, "11", 10) == STR2INT_SUCCESS);
    assert(i == 11);
    printf("%i", i);

    /* Negative number . */
    assert(str2int(&i, "-11", 10) == STR2INT_SUCCESS);
    assert(i == -11);
}

Исходный код источника


Разве это небезопасно, поскольку указатель out установлен на переменную, которая была определена локально в функции?
Не означает ли это, что после того, как преобразование выполнено и локальная переменная выйдет из области видимости, она может быть перезаписана, и мы больше не сможем полагаться на это значение?

Возможно, я просто что-то упустил, однако в настоящее время я не понимаю, как это безопасный способ сделать это.

Ответы [ 2 ]

0 голосов
/ 12 июня 2019

Параметр out - это указатель, который указывает на переменную i в main.Когда вы позже сделаете это:

*out = l;

Это не изменит out, но разыменует его и изменит переменную, на которую он указывает, а именно i в main.Поэтому, когда функция возвращает i, изменено.

Если out указывает на локальную переменную в str2int, то у вас будет проблема с указателем, указывающим на недопустимую память.

0 голосов
/ 12 июня 2019

*out = l; не устанавливает out, устанавливает *out. То есть, на что бы это ни указывало out, потому что оно разыменовывает указатель. Пока передается действительный адрес, функция будет изменять нелокальный объект.

...