我写了一个调用Unix脚本的C程序。该脚本将输出写入通过POPEN命令读取的文件。
在读取20多个字符的输出(例如“452088000104023512234”)时,通过现有代码将其转换为一些垃圾字符。
#include <stdlib.h>
#include <stdio.h>
#define OUTPUT_FILE_PATH "/td/mbb/Projects/MBNA/Work/java.txt"
#define SCRIPT_FILE_PATH "/td/mbb/Projects/MBNA/Work/R/TDEncryptDecrypt/TDEncryptDecrypt/src/java.sh"
void waitAndExecuteScript(char* input)
{
char scriptCmd[256];
sprintf(scriptCmd, "%s %s", SCRIPT_FILE_PATH, input);
int i = system(scriptCmd); //execute command string
FILE* fp = fopen ( OUTPUT_FILE_PATH , "rb" );
while (1)
{
if(fp == NULL)
{
usleep(1000);
fp = fopen (OUTPUT_FILE_PATH , "rb" );
}
else
{
fclose(fp);
break;
}
}
}
char * java (char* str1)
{
int i,l;
char * resultval;
char * buffer = NULL;
long lSize = 0;
size_t result = 0;
FILE* pFile = NULL;
char removeCmd[256];
waitAndExecuteScript(str1);
//******************************reading input data in a file ************************
pFile = fopen (OUTPUT_FILE_PATH , "rb" );
if (pFile==NULL)
{
fputs ("File error",stderr);
exit (1);
}
// obtain file size:
fseek (pFile , 0 , SEEK_END);
lSize = ftell (pFile);
rewind (pFile);
// allocate memory to contain the whole file:
buffer = (char*) malloc (sizeof(char)*lSize + 1); // 1 extra byte need to allocate to accomodate null character
if (buffer == NULL)
{
fputs ("Memory error",stderr);
exit (2);
}
// copy the file into the buffer:
result = fread (buffer,1,lSize,pFile);
if (result != lSize)
{
fputs ("Reading error",stderr);
exit (3);
}
/* the whole file is now loaded in the memory buffer. */
buffer[lSize] = '\0'; //make string null terminated so that printf will print it properly
printf("result from script %s", buffer);
resultval = buffer;
// terminate
fclose (pFile);
if(buffer != NULL)
{
free (buffer);
}
//wait here for 1ms
usleep(1000);
return resultval; //Return the result value of the script
}
答案 0 :(得分:3)
您的目的是:
运行一些外部命令以写入文件
轮询以查看您是否可以打开文件(位于waitAndExecuteScript
)
之后立即阅读文件(位于java
)。
此策略不起作用。除非您知道外部命令以原子方式创建文件(例如,通过将其写入另一个文件然后重命名),该文件将在完全写入之前存在并变为可读。请考虑以下顺序:
外部进程打开文件进行写入,但尚未写入任何内容
waitAndExecuteScript
成功打开空文件
java
读取空文件
外部进程写入数据。
如您所见,数据可能已部分写入。
您应该做的是检查正在完成写作的过程。或者,将其写入管道并使用阻塞读取。
答案 1 :(得分:1)
你的记忆管理也存在缺陷:
resultval = buffer;
...
if(buffer != NULL)
{
free (buffer);
}
...
return resultval; //Return the result value of the script
resultval = buffer
使指针变量resultval
指向与buffer
点相同的位置。但是你free()
- 编写了位于那里的内存块。因此,当您从resultval
函数返回时,java()
指向无效的内存位置。
如果你的平台是Linux,我建议你安装并使用Valgrind内存调试器来轻松发现这样的bug。