即使导致缓冲区溢出,将 int 转换为 string 仍然有效

Converting int to string still works even when causing buffer overflow

我正在尝试使用以下代码将 int 转换为 C 字符串:

static char* copyString(const char* str)  
{
    char* new_String = malloc(strlen(str) + 1);
    return strcpy(new_String, str);
}
static char* mallocIntToString(const int num)
{
    char s[10]; // *************
    sprintf(s, "%d", num);
    char* copy = copyString(s);

    return copy;
}

我在想我应该在行中插入的最大数字是多少 char s[10];.

我使用了 10,因为它是整数的最大位数。但是,当我使用 char s[9]; 时,这段代码也适用于我,试图将数字 2147483647 转换为字符串,这怎么可能?

I was wandering what is the biggest number I should insert in the line char s[10];.

您应该在 <limits.h> 中定义的 INT_MAXINT_MIN 之间插入最大长度。 INT_MIN应该是-2147483648,所以你需要11 + 1 = 12个字符(额外的一个是字符串终止符[=17=])。

正确的实施方式是:

static char* mallocIntToString(const int num)
{
    char *s;

    s = malloc(12);
    if (s == NULL)
        return NULL;

    sprintf(s, "%d", num);    
    // Should probably also check for error here.

    return s;
}

However, this code also works for me when I use char s[9];, trying to convert the number 2147483647 to string, how is it possible?

您正在调用未定义的行为,因为超出数组末尾的写入是未定义的行为。这样做时,任何事情都可能发生。该程序不能保证正常工作,但纯属巧合,它仍然似乎可以工作。您的代码中发生的事情是,由于变量是在堆栈上定义的,并且堆栈是可写的,因此再写入一两个字节不会有太大变化,因为程序仍在写入有效内存。尽管如此,它仍然是未定义的行为,应该不惜一切代价避免!

为了 100% 清楚,即使使用 char s[10];char s[11];,您也会调用未定义的行为,因为在 INT_MIN 的情况下,终止符将被写出数组界限。