现在我正在使用sprintf
,但想更改为snprintf
。
我的问题是,当我使用指针执行以下代码时,确保我没有缓冲区溢出的最佳方法是什么?
这是一个简单的代码示例,在我的代码中string_pos += get_line_to_buffer(&string[string_pos]);
被多次调用。因此,我要向缓冲区中添加大量数据,因此我想确保不会写太多。
int main(void){
char string[50];
size_t string_pos = 0;
string_pos += get_line_to_buffer(&string[string_pos]);
}
static size_t get_line_to_buffer(char *buffer){
char* p = buffer;
p += sprintf(p, "%d,%s,%s,%lu", version, fileName, Id, timestamp);
p += sprintf(p, ",%d,%d,%f", noOfObs, frequency, sum);
p += sprintf(p, ",%f,%f", latitude, longitude);
p += sprintf(p, ",%f,%d", speed, errorCode);
p += sprintf(p, "\r\n");
return p - buffer;
}
答案 0 :(得分:1)
请仔细阅读documentation of snprintf
(和/或Linux,snprintf(3))。请注意,它可能会由于返回负值而失败。您可能会对它的%n
感兴趣。
您需要知道缓冲区的大小。一个好的方法是将其作为第二个参数传递给您的get_line_to_buffer
函数:
ssize_t get_line_to_buffer(char *buffer, size_t siz) {
char* p = buffer;
char* start = buffer;
char* end = buffer + siz;
int n = 0;
if (p < end)
n = snprintf(p, siz, "%d, %s, %s, %lu", version, fileName, Id, timestamp);
else
n = snprintf(NULL, 0, "%d, %s, %s, %lu", version, fileName, Id, timestamp);
if (n<0) return -1;
p += n, siz -= n;
if (siz<0) return -1;
if (p < end)
n = snprintf(p, siz, ",%d,%d,%f", noOfObs, frequency, sum);
else
n = snprintf(NULL, 0, ",%d,%d,%f", noOfObs, frequency, sum);
if (n<0) return -1;
p += n; siz -= n;
return p - start;
}
实际上,如果您的系统上有asprintf(3),您可以考虑使用它。
您可以改为使用fmemopen(3)或open_memstream(3)打开内存流,并在其中使用fprintf
。
顺便说一句,您可以简单地执行一个snprintf
,但将其格式控制字符串分成几行:
int n = snprintf(p, siz,
"%d, %s, %s, %lu"
",%d,%d,%f",
version, fileName, Id, timestamp,
noOfObs, frequency, sum);