【问题标题】:Calculating size of C string before writing to buffer在写入缓冲区之前计算 C 字符串的大小
【发布时间】:2012-06-27 16:17:15
【问题描述】:

我是 C 的新手,想知道我处理某事的方式是否正确。我正在为http://nginx.com/ 创建一个模块,我正在为我的模块创建一个状态页面。

现在状态页面将包含一些基本的 HTML 和表格。这是我创建它的一些代码。

// Get size
size =
    sizeof("<table>") +
    sizeof("<tr><td align=\"right\">enabled:</td><td>YES</td></tr>") +
    sizeof("<tr><td align=\"right\">activated:</td><td>YES</td></tr>") +
    sizeof("<tr><td align=\"right\">connections/lt:</td><td>") + NGX_ATOMIC_T_LEN + sizeof(" / ") + NGX_ATOMIC_T_LEN + sizeof("</td></tr>") +
    sizeof("<tr><td align=\"right\">remain on: xxxx-xx-xx xx:xx:xx GMT</td><td></td></tr>") +
    sizeof("</table>");

// Start buffer
b = ngx_create_temp_buf(r->pool, size);
if (b == NULL) {
    return NGX_HTTP_INTERNAL_SERVER_ERROR;
}

// Start chain
out.buf = b;
out.next = NULL;

// Finish buffer
b->last = ngx_sprintf(b->last, "<table>");
b->last = ngx_sprintf(b->last, "<tr><td align=\"right\">enabled:</td><td>%s</td></tr>", alcf->enabled ? "YES" : "NO");
b->last = ngx_sprintf(b->last, "<tr><td align=\"right\">activated:</td><td>%s</td></tr>", alcf->activated ? "YES" : "NO");
b->last = ngx_sprintf(b->last, "<tr><td align=\"right\">connections/lt:</td><td>%uA / %uA</td></tr>", ac, alcf->connections_activate);
b->last = ngx_sprintf(b->last, "<tr><td align=\"right\">remain on:</td><td>");
b->last = !alcf->activatedEndTime ? ngx_sprintf(b->last,"") : ngx_http_cookie_time(b->last, alcf->activatedEndTime);
b->last = ngx_sprintf(b->last, "</td></tr>");
b->last = ngx_sprintf(b->last, "<table>");

这是唯一有效的方法吗,我觉得必须编写两次 HTML 代码是错误的,一次是获取大小以使缓冲区膨胀,另一次是实际存储在缓冲区中。是否有任何其他解决方案。我正在努力使其尽可能保持内存效率。

【问题讨论】:

标签: c string nginx buffer


【解决方案1】:

请记住:sizeof 是一个编译时运算符,因此您的sizeof 语句不会使用任何额外的内存。

所以是的,这是尽可能高效的,假设您的编译器甚至有少量优化。

【讨论】:

  • 谢谢你,只是不想继续写,除非它是正确的。
【解决方案2】:

我认为您有一个错误 - 您忘记为终止 \0 保留空间。

您对sizeof 的使用有效,但会迫使您重复HTML 的每个部分。有一天你会更新sprintf 行中的HTML,而忘记更新sizeof 行中的副本,这会导致内存溢出。

更好的方法是将字符串保留一次,然后使用strlen 获取大小。
这是这个想法的一个例子。它远非完美,但它节省了大部分重复。

struct html_part {
   const char *text;
   size_t extra_len;
};
struct html_part html_parts[] = {
    { "<table>", 0 }
    { "<tr><td align=\"right\">enabled:</td><td>%s</td></tr>", 3-2 } // YES=3, %s=2
    ...
};
// Calculate the space needed
len = 0;
for (i=0;i<sizeof(html_parts)/sizeof(html_parts[0]);i++) {
    len += strlen(html_parts[i].text) + html_parts[i].extra_len;
}
len++;  // For the terminating null
...
// Print the data
b->last = ngx_sprintf(b->last, html_parts[0]);
b->last = ngx_sprintf(b->last, html_parts[1], alcf->enabled ? "YES" : "NO");

【讨论】:

  • 这是一个好主意,正是我想要的,谢谢!
猜你喜欢
  • 2012-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-06
相关资源
最近更新 更多