我认为这是使用 sprintf 的常用方法:
char pText[x];
sprintf(pText, "helloworld %d", Count );
但究竟会发生什么,如果 char 指针分配的内存比打印到的少?
即如果x 小于sprintf 的第二个参数的长度怎么办?
我在问,因为我在 sprintf 语句之后的代码中出现了一些奇怪的行为。
一般不可能“确切地”回答会发生什么。这样做会调用所谓的未定义行为,这基本上意味着任何事情都可能发生。
最好避免这种情况,并在可用的情况下使用安全功能:
char pText[12];
snprintf(pText, sizeof pText, "helloworld %d", count);
请注意如何snprintf()
采用额外的参数,即缓冲区大小,并且不会写入超出空间的内容。
这是一个常见错误,会在 char 数组被覆盖后导致内存占用。因此,例如,在 char 数组之后的内存中可能有一些 int 或另一个数组,这些会被文本覆盖。
在此处查看有关整个问题(缓冲区溢出)的详细说明。还有一条评论说,某些体系结构提供了一个 snprintf 例程,该例程具有定义最大长度的第四个参数(在您的情况下为 x)。如果您的编译器不知道它,您也可以自己编写它以确保不会出现此类错误(或者只是检查您是否始终有足够的空间分配)。
请注意,此类错误之后的行为是未定义的,并且可能导致非常奇怪的错误。变量通常在可被 4 整除的内存位置对齐,因此在大多数情况下,您有时不会注意到错误,在大多数情况下,您已经写了太多的一两个字节(即忘记为 NUL 腾出位置),但在其他情况下会出现奇怪的错误案例。这些错误很难调试,因为其他变量会发生变化,并且错误通常会发生在代码的完全不同的部分。
这称为缓冲区溢出。
sprintf
将覆盖恰好遵循pText
地址的内存。由于pText
在栈上,sprintf
可以覆盖局部变量、函数参数和返回地址,导致各种错误。这种代码会导致许多安全漏洞——例如,攻击者使用缓冲区溢出来编写指向他自己代码的新返回地址。
这种情况下的行为是未定义的。通常,您会崩溃,但您也可能不会看到任何不良影响,不相关的变量中出现奇怪的值等等。您的代码还可能调用错误的函数、格式化您的硬盘驱动器并杀死其他正在运行的程序。最好通过为缓冲区分配更多内存来解决此问题。
我已经这样做了很多次,你会收到内存损坏错误。AFAIK,我记得我做过这样的事情:-
vector<char> vecMyObj(10);
vecMyObj.resize(10);
sprintf(&vecMyObj[0],"helloworld %d", count);
但是当调用vector的析构函数时,我的程序收到内存损坏错误,如果大小小于10,它将成功运行。
你会拼写缓冲区溢出吗?一种可能的结果是堆栈损坏,并使您的应用容易受到基于堆栈的利用。