为什么要使用Asprintf?

我很难理解你为什么需要asprintf。 它在说明书中说

函数asprintf()和vasprintf()类似于sprintf(3)和vsprintf(3),除了它们分配一个足够大的string来保存包括终止空字节的输出,并且通过第一个参数返回一个指向它的指针。 这个指针应该被传递给free(3),当不再需要的时候释放分配的存储。

所以这里是我想要了解的例子:

asprintf(&buffer, "/bin/echo %s is cool", getenv("USER")); 

如果缓冲区分配一个足够大的string与说char * =(string)有什么区别,

如果使用sprintf()或vsprintf(),则需要首先分配缓冲区,并且需要确保缓冲区足够大,以包含sprintf写入的内容。 否则,sprintf会高兴地覆盖缓冲区末尾以外的所有内存。

 char* x = malloc(5 * sizeof(char)); sprintf(x,"%s%s%s", "12", "34", "56"); // writes "123456" +null but overruns the buffer 

…在分配给x的空间结束之后写入'6'并终止null ,这会破坏其他一些variables或导致分段错误。

如果你幸运的话,它会在分配的块之间的内存中践踏,这次不会有什么坏处。 这会导致间歇性的错误 – 最难诊断的错误。 使用像ElectricFence这样的工具会导致超限失效。

提供超长input的非恶意用户可能会导致程序意外行为。 恶意用户可以利用这种方式来获取他们自己的可执行代码到系统中。

一个防范措施就是使用snprintf() ,它会将string截断为您提供的最大长度。

 char *x = malloc(5 * sizeof(char)); int size = snprintf(x, 5, "%s%s%s", "12", "34", "56"); // writes "1234" + null 

返回值size是空间可用时写入的长度 – 不包括终止空值

在这种情况下,如果size大于或等于5,那么就知道发生了截断 – 如果您不想截断,可以分配一个新的string并再次尝试snprintf()

 char *x = malloc(BUF_LEN * sizeof(char)); int size = snprintf(x, 5, "%s%s%s", "12", "34", "56"); if(size >= BUF_LEN) { realloc(&x,(size + 1) * sizeof(char)); snprintf(x, 5, "%s%s%s", "12", "34", "56"); } 

(这是一个非常天真的algorithm,但它说明了一点)

asprintf()为你做了这一步 – 计算string的长度,分配这个内存量,并把string写入它。

 char *x; int size = asprintf(&x, "%s%s%s", "12", "34", "56"); 

在所有情况下,一旦你完成了x你需要释放它,或者你泄漏内存:

 free(x); 

asprintf()是一个隐含的malloc() ,所以你必须检查它的工作,就像你用malloc()或任何其他系统调用一样。

 if(size == -1 ) { /* deal with error in some way */ } 

请注意, asprintf()是libc的GNU和BSD扩展的一部分 – 您不能确定它将在每个C环境中都可用。 sprintf()snprintf()是POSIX和C99标准的一部分。

好处是安全。

许多程序已经允许系统漏洞发生时,用户提供的数据填充程序员提供的缓冲区溢出。

asprintf为你分配缓冲区保证不会发生。

但是,您必须检查asprintf的返回值,以确保内存分配实际上成功。 见http://blogs.23.nu/ilja/2006/10/antville-12995/

Interesting Posts