fprintf 在特定字符串上失败,而 shell 函数使用它没有崩溃
fprintf fails on specific string while shell functions use it with no crash
简短版本:我有一个 C++ 代码,它使用 C 调用 fprintf(stdout, some_cpp_str.c_str())
并在调用期间崩溃。前 4 次调用都很好,只有第 5 次崩溃,我不知道为什么 (怀疑字符串中有不可读的字符)。我发布的第一个代码主要是 C,所以我发布了另一个代码,除了 fprintf
(代码添加在问题的底部)之外只有 C++。崩溃(始终)发生在嵌入式设备上。在我自己的电脑上,代码 运行s fine
长版:
我有一个代码可以从文本中读取行,并将它们推送到一个字符串向量中。为了检查我的进度,我还在矢量填充后 fprintf
将它们显示在屏幕上:
int main(){
char err_msg[256], * line = NULL, *in_file = "...", *keyword = "blah";
size_t len = 0;
ssize_t num_bytes_read;
int i = 1;
std::vector<std::string> lines_vector;
FILE * fp = fopen(in_file, "r");
if (!fp) {
fprintf(stdout,"can't open file %s for reading\n", in_file);
goto EXIT;
}
while ((num_bytes_read = getline(&line, &len, fp)) != -1) {
/* if found keyword inside line */
if (strstr(line, keyword)) {
/* add 3 lines (entry heading, entry body, newline)*/
lines_vector.push_back(std::string(line));
for(int lines_to_copy = 2; lines_to_copy > 0; lines_to_copy--) {
if((num_bytes_read = getline(&line, &len, fp)) == -1) {
fprintf(stdout,"can't read line from %s\n", in_file);
goto EXIT;
}
lines_vector.push_back(std::string(line));
}
}
}
fprintf(stdout,"finished reading from file\n");
EXIT:
fclose(fp);
free(line);
for (std::vector<std::string>::iterator it = lines_vector.begin() ; it != lines_vector.end(); ++it, ++i) {
fprintf(stdout, "%d)", i);
fprintf(stdout, "%s", (*it).c_str());
}
return 0;
}
这在我的 VM 上运行良好,但我也在嵌入式设备上 运行 它,它总是在特定线路上崩溃。该行是:
certificates local generate name localcert common-name sf country(region) AB auto-regenerate-days 12 auto-regenerate-days-warning 11 e-mail X@Y.com locality(city) Z organization Q organization-unit T scep-password-string 57E6CA35452E72E4D1BC4518260ABFC7 scep-url http://0.0.0.0/X/Y/ state(province) s
我认为线路本身没有问题(因为它不会在我的 VM 上崩溃)。尝试将其打印到文件而不是屏幕时,它不会崩溃:
for (std::vector<std::string>::iterator it = lines_vector.begin(); it != lines_vector.end(); ++it){
sprintf(tmp, "echo \"%s\" >> /X/Y/Z.txt", (*it).c_str());
OS_run(tmp); // run this command on sh shell
}
因为它只在我的嵌入式而不是我的 VM 上崩溃,我认为该文件已损坏。会不会是字符串内部有一个无效的字符导致崩溃 fprintf
,而不是 echo
?
我尝试将这段代码翻译成正确的 C++,但我仍然在最后一个字符串的中间发生崩溃。我知道混合 C/C++ 不好,但 c_str()
不应该是 std::string
和 char * (fprintf
期望的)之间的适当接口吗?
如果不是这个,那么在 fprintf
期间什么可能会崩溃?
int main()
{
std::vector<std::string> lines_vector;
std::ifstream infile(in_file);
std::string line;
int counter = 1;
while (std::getline(infile, line)) {
if (line.find(keyword, 0) != std::string::npos) {
lines_vector.push_back(line);
for(int lines_to_copy = 2; lines_to_copy > 0; lines_to_copy--) {
std::getline(infile, line);
lines_vector.push_back(line);
}
}
}
for (std::vector<std::string>::iterator it = lines_vector.begin(); it != lines_vector.end(); ++it){
fprintf(stdout, "%d)%s", counter++, (*it).c_str());
}
}
在嵌入式设备上,动态内存分配可能会失败。这意味着您绝对必须控制所有可能的分配(即使在非嵌入式设备上您也应该控制,但崩溃风险要低得多......)。你真的应该:
while ((num_bytes_read = getline(&line, &len, fp)) != -1) {
...
}
if (line == NULL) {
perror("getline could not allocate buffer");
}
这不会解决任何问题,但至少你会知道会发生什么。
我在这里尊重你的编码风格,大量使用 C 库并使用 goto
。但我必须建议你不要在 C++ 程序中这样做。
C 库曾经包含在 C++ 标准库中,因为早期的 C++ 实现缺少太多功能。在现代 C++ 中,goto
将被禁止,所有原始 C 字符串和 C io 函数也是如此(非常特殊的用例除外)。而C++自带的getline
版本(在header<string>
中)直接填充了一个std::string
。如果学习 C++,你真的应该尽量避免使用 C 构造。
根据 Ben Voigt 的评论,如果您想避免动态分配,则有使用旧式 C 库的正确用例。但在那种情况下,您还应该避免 std::string
和 std::vector
简短版本:我有一个 C++ 代码,它使用 C 调用 fprintf(stdout, some_cpp_str.c_str())
并在调用期间崩溃。前 4 次调用都很好,只有第 5 次崩溃,我不知道为什么 (怀疑字符串中有不可读的字符)。我发布的第一个代码主要是 C,所以我发布了另一个代码,除了 fprintf
(代码添加在问题的底部)之外只有 C++。崩溃(始终)发生在嵌入式设备上。在我自己的电脑上,代码 运行s fine
长版:
我有一个代码可以从文本中读取行,并将它们推送到一个字符串向量中。为了检查我的进度,我还在矢量填充后 fprintf
将它们显示在屏幕上:
int main(){
char err_msg[256], * line = NULL, *in_file = "...", *keyword = "blah";
size_t len = 0;
ssize_t num_bytes_read;
int i = 1;
std::vector<std::string> lines_vector;
FILE * fp = fopen(in_file, "r");
if (!fp) {
fprintf(stdout,"can't open file %s for reading\n", in_file);
goto EXIT;
}
while ((num_bytes_read = getline(&line, &len, fp)) != -1) {
/* if found keyword inside line */
if (strstr(line, keyword)) {
/* add 3 lines (entry heading, entry body, newline)*/
lines_vector.push_back(std::string(line));
for(int lines_to_copy = 2; lines_to_copy > 0; lines_to_copy--) {
if((num_bytes_read = getline(&line, &len, fp)) == -1) {
fprintf(stdout,"can't read line from %s\n", in_file);
goto EXIT;
}
lines_vector.push_back(std::string(line));
}
}
}
fprintf(stdout,"finished reading from file\n");
EXIT:
fclose(fp);
free(line);
for (std::vector<std::string>::iterator it = lines_vector.begin() ; it != lines_vector.end(); ++it, ++i) {
fprintf(stdout, "%d)", i);
fprintf(stdout, "%s", (*it).c_str());
}
return 0;
}
这在我的 VM 上运行良好,但我也在嵌入式设备上 运行 它,它总是在特定线路上崩溃。该行是:
certificates local generate name localcert common-name sf country(region) AB auto-regenerate-days 12 auto-regenerate-days-warning 11 e-mail X@Y.com locality(city) Z organization Q organization-unit T scep-password-string 57E6CA35452E72E4D1BC4518260ABFC7 scep-url http://0.0.0.0/X/Y/ state(province) s
我认为线路本身没有问题(因为它不会在我的 VM 上崩溃)。尝试将其打印到文件而不是屏幕时,它不会崩溃:
for (std::vector<std::string>::iterator it = lines_vector.begin(); it != lines_vector.end(); ++it){
sprintf(tmp, "echo \"%s\" >> /X/Y/Z.txt", (*it).c_str());
OS_run(tmp); // run this command on sh shell
}
因为它只在我的嵌入式而不是我的 VM 上崩溃,我认为该文件已损坏。会不会是字符串内部有一个无效的字符导致崩溃 fprintf
,而不是 echo
?
我尝试将这段代码翻译成正确的 C++,但我仍然在最后一个字符串的中间发生崩溃。我知道混合 C/C++ 不好,但 c_str()
不应该是 std::string
和 char * (fprintf
期望的)之间的适当接口吗?
如果不是这个,那么在 fprintf
期间什么可能会崩溃?
int main()
{
std::vector<std::string> lines_vector;
std::ifstream infile(in_file);
std::string line;
int counter = 1;
while (std::getline(infile, line)) {
if (line.find(keyword, 0) != std::string::npos) {
lines_vector.push_back(line);
for(int lines_to_copy = 2; lines_to_copy > 0; lines_to_copy--) {
std::getline(infile, line);
lines_vector.push_back(line);
}
}
}
for (std::vector<std::string>::iterator it = lines_vector.begin(); it != lines_vector.end(); ++it){
fprintf(stdout, "%d)%s", counter++, (*it).c_str());
}
}
在嵌入式设备上,动态内存分配可能会失败。这意味着您绝对必须控制所有可能的分配(即使在非嵌入式设备上您也应该控制,但崩溃风险要低得多......)。你真的应该:
while ((num_bytes_read = getline(&line, &len, fp)) != -1) {
...
}
if (line == NULL) {
perror("getline could not allocate buffer");
}
这不会解决任何问题,但至少你会知道会发生什么。
我在这里尊重你的编码风格,大量使用 C 库并使用 goto
。但我必须建议你不要在 C++ 程序中这样做。
C 库曾经包含在 C++ 标准库中,因为早期的 C++ 实现缺少太多功能。在现代 C++ 中,goto
将被禁止,所有原始 C 字符串和 C io 函数也是如此(非常特殊的用例除外)。而C++自带的getline
版本(在header<string>
中)直接填充了一个std::string
。如果学习 C++,你真的应该尽量避免使用 C 构造。
根据 Ben Voigt 的评论,如果您想避免动态分配,则有使用旧式 C 库的正确用例。但在那种情况下,您还应该避免 std::string
和 std::vector