C - 安全地解析和发送大量无休止的流中的许多字符串
C - Safely parse and send many strings in large endless stream
我对 C 没有多少经验
我有一个连接到几乎无限文本流 (25Mb/s) 的小型 C 程序。
我想用 zeromq 将字符串的每一行作为单独的消息发送。
因此,我将每秒发送数千条消息,在发送每条消息之前,我想操作通过套接字发送的字符串:
假设我开始于:
Quote {0.0.0.0} XXX <1>A<2>B<3>C
我要
XXX Quote <1>A<2>B<3>C
一般来说,我怎样才能安全地执行此操作,以免 运行 发生内存泄漏?我会有这样的事情(举个例子,main
函数实际上是一个具有不同字符的永无止境的循环):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* parse(const char* input) {
char* output;
char* input_copy = strdup(input);
char* token;
char* first;
char* third;
char* fourth;
token = strtok(input_copy, " ");
first = token;
for (int i = 0; i < 3; i++)
{
token = strtok(NULL, " ");
if (i == 1) third = token;
if (i == 2) fourth = token;
}
asprintf(&output, "%s %s %s", third, first, fourth);
return output;
free(output);
}
int main(void)
{
const char *a = "Quote {0.0.0.0} XXX <1>A<2>B<3>C";
//SEND_MESSAGE(parse(a));
return 0;
}
这行得通吗?
像这样更改您的 main
:
int main(void)
{
const char *a = "Quote {0.0.0.0} XXX <1>A<2>B<3>C";
char *buff = parse(a);
SEND_MESSAGE(buff);
free(buff);
return 0;
}
并删除parse
中return
后面的free
。您还需要为 output
:
分配足够的 space
char *output = malloc(1024); //for example
正如对问题的评论所提到的,最好将 output
声明为全局变量(因此将上一行放在 parse
之外),并将 free
声明为全局变量程序的最后(在输入流的字符串循环之外)。这确实使程序更快。
如果您知道(或可以确定)每个 first
、second
、third
和 fourth
的最大大小是多少,您可以消除内存泄漏的所有可能性,只需为每个内存泄漏使用固定大小的缓冲区。你说你的 25M/sec 文本被分解成 行 ,所以大概你正在使用 面向行的输入 函数(例如 fgets
或 getline
) 从流中读取。在这种情况下,您也可以只使用最大行长度 (X4) 来确保您的固定缓冲区足够。
您正在使用 space
作为分隔符标记为 first
、second
、third
和 fourth
,那么为什么不使用 sscanf
?如果您想使用 parse
函数,只需将缓冲区作为参数传递即可。
如果您可以确定一个最大值并且您在 space
上标记化,您可以做一些简单的事情:
#include <stdio.h>
#define MAXC 1024
int main(void)
{
const char *a = "Quote {0.0.0.0} XXX <1>A<2>B<3>C";
char first[MAXC] = "",
second[MAXC] = "",
third[MAXC] = "",
fourth[MAXC] = "";
/* read a line from the stream and simply call sscanf */
if (sscanf (a, " %s %s %s %s", first, second, third, fourth) == 4)
printf ("%s %s %s\n", third, first, fourth);
return 0;
}
(printf
只是举例,根据需要将结果传给你的zeromq)
例子Use/Output
$ ./bin/staticbuf
XXX Quote <1>A<2>B<3>C
(这会产生极大简化代码的副作用,并且可能还会大大加快代码速度)。
如果您不能自信地确定最大大小,那么您将陷入 malloc
/free
的开销(或使用 POSIX getline
并让它处理分配)。
我对 C 没有多少经验
我有一个连接到几乎无限文本流 (25Mb/s) 的小型 C 程序。
我想用 zeromq 将字符串的每一行作为单独的消息发送。
因此,我将每秒发送数千条消息,在发送每条消息之前,我想操作通过套接字发送的字符串:
假设我开始于:
Quote {0.0.0.0} XXX <1>A<2>B<3>C
我要
XXX Quote <1>A<2>B<3>C
一般来说,我怎样才能安全地执行此操作,以免 运行 发生内存泄漏?我会有这样的事情(举个例子,main
函数实际上是一个具有不同字符的永无止境的循环):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* parse(const char* input) {
char* output;
char* input_copy = strdup(input);
char* token;
char* first;
char* third;
char* fourth;
token = strtok(input_copy, " ");
first = token;
for (int i = 0; i < 3; i++)
{
token = strtok(NULL, " ");
if (i == 1) third = token;
if (i == 2) fourth = token;
}
asprintf(&output, "%s %s %s", third, first, fourth);
return output;
free(output);
}
int main(void)
{
const char *a = "Quote {0.0.0.0} XXX <1>A<2>B<3>C";
//SEND_MESSAGE(parse(a));
return 0;
}
这行得通吗?
像这样更改您的 main
:
int main(void)
{
const char *a = "Quote {0.0.0.0} XXX <1>A<2>B<3>C";
char *buff = parse(a);
SEND_MESSAGE(buff);
free(buff);
return 0;
}
并删除parse
中return
后面的free
。您还需要为 output
:
char *output = malloc(1024); //for example
正如对问题的评论所提到的,最好将 output
声明为全局变量(因此将上一行放在 parse
之外),并将 free
声明为全局变量程序的最后(在输入流的字符串循环之外)。这确实使程序更快。
如果您知道(或可以确定)每个 first
、second
、third
和 fourth
的最大大小是多少,您可以消除内存泄漏的所有可能性,只需为每个内存泄漏使用固定大小的缓冲区。你说你的 25M/sec 文本被分解成 行 ,所以大概你正在使用 面向行的输入 函数(例如 fgets
或 getline
) 从流中读取。在这种情况下,您也可以只使用最大行长度 (X4) 来确保您的固定缓冲区足够。
您正在使用 space
作为分隔符标记为 first
、second
、third
和 fourth
,那么为什么不使用 sscanf
?如果您想使用 parse
函数,只需将缓冲区作为参数传递即可。
如果您可以确定一个最大值并且您在 space
上标记化,您可以做一些简单的事情:
#include <stdio.h>
#define MAXC 1024
int main(void)
{
const char *a = "Quote {0.0.0.0} XXX <1>A<2>B<3>C";
char first[MAXC] = "",
second[MAXC] = "",
third[MAXC] = "",
fourth[MAXC] = "";
/* read a line from the stream and simply call sscanf */
if (sscanf (a, " %s %s %s %s", first, second, third, fourth) == 4)
printf ("%s %s %s\n", third, first, fourth);
return 0;
}
(printf
只是举例,根据需要将结果传给你的zeromq)
例子Use/Output
$ ./bin/staticbuf
XXX Quote <1>A<2>B<3>C
(这会产生极大简化代码的副作用,并且可能还会大大加快代码速度)。
如果您不能自信地确定最大大小,那么您将陷入 malloc
/free
的开销(或使用 POSIX getline
并让它处理分配)。