如何在Eclipse运行的C应用程序中避免不可复制字符
我正在使用一个C应用程序,该应用程序由运行在Eclipse中的Java应用程序测试。 Java应用程序使用标准方式运行C应用程序:如何在Eclipse运行的C应用程序中避免不可复制字符,c,eclipse,visual-studio,printf,C,Eclipse,Visual Studio,Printf,我正在使用一个C应用程序,该应用程序由运行在Eclipse中的Java应用程序测试。 Java应用程序使用标准方式运行C应用程序: Runtime.getRuntime().exec(cmdline) (包含C应用程序可执行文件的cmdline) C应用程序很可能使用Visual Studio的vsprintf()函数来编写内容,但在某些情况下,似乎会打印不可复制的字符,如您所见: put_log(LOG_INFO, "Waiting for writing thread\n"); (put
Runtime.getRuntime().exec(cmdline)
(包含C应用程序可执行文件的cmdline
)
C应用程序很可能使用Visual Studio的vsprintf()
函数来编写内容,但在某些情况下,似乎会打印不可复制的字符,如您所见:
put_log(LOG_INFO, "Waiting for writing thread\n");
(put_log()
这在Eclipse中显示为:
INFO : aiting for writing thread
正如你所看到的,“W”已经消失了,最重要的是,当我试图复制上面提到的行时,我只看到:
INFO :
我的印象是字母W
已被一个字符替换,无法复制到Windows剪贴板。当这发生在相当大的输出的中间时,这是非常令人讨厌的。
有人知道发生了什么事,我如何解决这个问题吗
根据Fluter的要求,特此摘录put_log()
函数:
void put_log(const char *fmt, ...)
{
static char str[16384];
char* args;
char* p = str;
strcpy(str, "INFO: ");
p = str + strlen(str);
_crt_va_start(args, fmt);
vsprintf(p, fmt, args);
_crt_va_end(args);
...
}
(第一个参数(LOG_INFO
)从此摘录中删除,并替换为“INFO:”
硬编码字符串,以便于简化)
请参考以下低层功能的位置:
- _crt\u va\u start():c:\Program Files(x86)\Microsoft Visual Studio 12.0\VC\include\stdarg.h
- _crt\u va\u end():c:\Program Files(x86)\Microsoft Visual Studio 12.0\VC\include\stdarg.h
- vsprintf():C:\ProgramFiles(x86)\Microsoft Visual Studio 12.0\VC\crt\src\vsprintf.C
谢谢假设\u crt\u va\u start
的行为类似于标准Cva\u start
,那么您需要在某个地方声明va\u列表
,而不是使用一些未初始化的字符指针。它似乎有效的原因可能是因为va列表不存在类型安全性(因此使用它们开始是不好的做法)
改为这样做:
#include <stdarg.h>
void put_log(const char *fmt, ...)
{
static char str[16384];
va_list va;
char* p = str;
strcpy(str, "INFO: ");
p = str + strlen(str);
va_start(va, fmt);
vsprintf(p, fmt, va);
va_end(va);
}
#包括
作废放置日志(常量字符*fmt,…)
{
静态字符str[16384];
va_列表va;
char*p=str;
strcpy(str,“信息:”);
p=str+strlen(str);
va_启动(va,fmt);
vsprintf(p、fmt、va);
va_端(va);
}
您没有发布如何在控制台上打印日志,请确保使用正确的功能打印日志,例如fprintf(stderr,str)代码>
其次,这里使用的是静态缓冲区,当函数被并发调用(可能由多个线程调用)时,它会受到数据竞争的影响。显然,每个日志都会覆盖缓冲区,在这里使用static没有意义,但会带来数据损坏的问题
void put_log(const char *fmt, ...)
{
char str[16384];
char* args;
char* p = str;
va_list list;
strcpy(str, "INFO: ");
p = str + strlen(str);
va_start(list, fmt);
vsprintf(p, fmt, list);
va_end(list);
fprintf(stderr, str);
}
请发布C程序的日志。为什么你的示例说INFO:
,而代码说INFO:
。这是一个输入错误还是错误的一部分?Hello@Lundin,这确实是一个输入错误。您是否从其他地方复制了字符串“等待写入线程\n”或键入了它?这种行为可能是因为字符“W”是您的终端不支持的某种Unicode。什么是中断代码>在内部执行放置日志()
?您正在使用的格式字符串是什么?奇怪,因为put\u LOG
应该准备一个正确的字符串,因为似乎只涉及普通ASCII。。。但是,如果代码的另一部分中存在未定义的行为,则可能会发生任何事情。你能建立一个能证明问题的模型吗?你在Eclipse之外用普通文本编辑器控制日志文件了吗?很抱歉,Lundin,为了有一个简短的源代码摘录,我扔掉了太多的行:va_list
是在函数开始时声明的,所以事实上,我的源代码与你建议的源代码一模一样。与此同时,我看到消息的第一个字母被ASCII代码0(零)的字符所取代。@Dominique因此,与其浪费每个人的时间,为什么不发布一份准确代码的副本/粘贴?我理解你的问题,Lundin,但我的公司在这件事上非常严格。正如我提到的,函数vsprintf(p,fmt,va)使用了code>,它似乎是一个Visual Studio print()函数。@Dominique否,vsprintf
将格式化字符串打印到指向p的缓冲区中,它不会将缓冲区打印到文件中。这就是为什么我说要调用fprintf
。我在末尾添加了fprintf
(与源代码一样),那么程序现在输出什么?程序的行为与前面提到的完全一样:在某些情况下,输出的第一个字符消失了。