【问题标题】:wrong usage of sprintf?sprintf 的错误用法?
【发布时间】:2010-11-18 15:42:17
【问题描述】:

我有简单的测试程序

#include <stdio.h>
int main( int argc , char* argv[] )
{
  unsigned int number=2048;

  char* cpOut;
  char cOut[4]; 
  cpOut=(char*)&cOut[0];
  printf("cOut address= %x \n",&cOut[0]);
  printf("cpOut address = %x \n",cpOut);

  sprintf(&cOut[0],"%d \n", number);

  printf("cOut address= %x \n",&cOut[0]);
  printf("cpOut address = %x \n",cpOut);
};

在 Linux、gcc 4.3.4 上测试运行:

user@server /tmp $ ./a.out 
cOut address= f9f41880 
cpOut address = f9f41880 
cOut address= f9f41880 
cpOut address = f9f41880 

在 Solaris 10、Sun C++ 5.10 上测试运行:

bash-3.00$ ./a.out
cOut address= 8047488
cpOut address = 8047488
cOut address= 8047488
cpOut address = 8000a20

谁能解释一下为什么指针 cpOut 被调用 sprintf 函数覆盖?

【问题讨论】:

    标签: c++ c printf


    【解决方案1】:

    由于字符串 "2048 \n" 不适合 char cOut[4];,因此您正在创建缓冲区溢出。

    【讨论】:

      【解决方案2】:

      您正在将 7 个字节 ("2048 \n" + NUL) 写入堆栈上大小为 4 的数组中。这将覆盖堆栈上低于它的 3 个字节,在本例中为cpOutcpOut 的新值向您展示了这一点:第一个字节未更改 0x08,接下来的 3 个字节是您正在写入的字符串的最后三个字节:00 (NUL)、0a ('\n')、20 ( '')。

      【讨论】:

        【解决方案3】:

        我认为这是缓冲区溢出的情况。尝试使 cOut 更大,同时将 sprintf 替换为更安全的 snprintf:

        sprintf(&cOut[0],"%d \n", number);
        

        应该改为

        snprintf(cOut,sizeof(cOut),"%d \n", number);
        

        【讨论】:

          【解决方案4】:

          这一行:

          sprintf(&cOut[0],"%d \n", number);
          

          写入 7 个字符:“2048 \n\0”,但只有其中 4 个字符的空间。值 0x8000a20 包含(按相反顺序):空格、换行符和字符 0。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-11-03
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多