如何在Eclipse运行的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

我正在使用一个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_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
的行为类似于标准C
va\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),它似乎是一个Visual Studio print()函数。@Dominique否,
vsprintf
将格式化字符串打印到指向p的缓冲区中,它不会将缓冲区打印到文件中。这就是为什么我说要调用
fprintf
。我在末尾添加了
fprintf
(与源代码一样),那么程序现在输出什么?程序的行为与前面提到的完全一样:在某些情况下,输出的第一个字符消失了。