zsh:传递结果文件名编译C程序时总线错误



在下面的C程序中,有不同的输入参数。其中一个参数-f用于指定结果的文件名

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#define SOURCES 4
#define NUM_T 1000
char *prgname;
char usage[]="%s [-uUdipT] -f filenamen";
int main(int argc, char *argv[])
{
FILE *filefd;
char *fname;
int  lt;            /* lower threshold */
int  ut;            /* upper threshold */
int  T;             /* Actualization time (cells) */
double RDF, RIF;        /* Rate Decrease-Increate Factor */
double PCR;         /* Peak Cell Rate */
int qlen;           /* queue length */
int bitEFCI[SOURCES];   /* EFCI bit */
double ACR [SOURCES];   /* Allowed Cell Rate */
double mean[SOURCES];   /* Mean Cell Rate */
int i, t;           /* control variables */
double ACRacc;
prgname = strrchr(argv[0], '/');
if (prgname == (char *)NULL) prgname = argv[0];
else prgname++; 

/********************************************/
/* DEFAULT VALUES & INICIALIZATION          */
/********************************************/

fname = (char *)malloc(200*sizeof(char));
fname = "abr.res";
ut = 550;
lt = 450;
RDF = 0.4;
RIF = 0.02;
PCR = 150E6;
T = 70;
qlen = 0;
for (i=0; i < SOURCES; i++)
{bitEFCI[i] = 0; ACR[i] = 0.0; mean[i] = 0.0;}
/********************************************/
/* USER COMMAND LINE VALUES                 */
/********************************************/

while (1)
{
int c;
c = getopt(argc, argv, "u:U:d:i:p:T:f:h");
if (c == EOF) break;
switch (c)
{
case 'h': printf(usage, prgname);
fputs("-htHelpn", stdout);
fputs("-utLower threshold (cells)n", stdout);
fputs("-UtUpper threshold (cells)n", stdout);
fputs("-dtDecrement factorn", stdout);
fputs("-itIncrement factorn", stdout);
fputs("-ptPeak cell rate (Mbps)n", stdout);
fputs("-TtActualization period (cells)n", stdout);
fputs("-ftResults file namen", stdout);
exit(0);
case 'u': lt = atoi(optarg);
break;
case 'U': ut = atoi(optarg);
break;
case 'd': RDF = atof(optarg);
break;
case 'i': RIF = atof(optarg);
break;
case 'p': PCR = atof(optarg);
break;
case 'T': T = atoi(optarg);
break;
case 'f': strcpy(fname, optarg);
break;
default : fprintf(stderr, usage, prgname); exit(1);
}
}

if ((filefd = fopen(fname, "w")) == NULL)
{perror("fopen"); exit(1);}
/********************************************/
/* MAIN LOOP                                */
/********************************************/

for (t = 1; t<= NUM_T; t++)
{
ACRacc = 0.0;
fprintf(filefd, "%dt", t);
for (i=0; i < SOURCES; i++)
{
if (bitEFCI[i] == 0)
ACR[i] = (ACR[i]+PCR*RIF>PCR)?(PCR):(ACR[i]+PCR*RIF);
else ACR[i] *= RDF;
mean[i] += (ACR[i]-mean[i])/(double)t;
ACRacc  += ACR[i];
fprintf(filefd, "%4.1ft%4.1ft", ACR[i]/1E6, mean[i]/1E6);
}

qlen += (int)(ACRacc*T*424/PCR);
qlen  = (qlen<=T*424)?(0):(qlen - T*424);
fprintf(filefd, "%dn", qlen/424);

for (i=0; i < SOURCES; i++)
{
if (qlen >= ut*424) bitEFCI[i] = 1;
else if (qlen < lt*424) bitEFCI[i] = 0;
}
fflush(filefd);
}   
fclose(filefd);
exit(0);
}

我用

编译过
gcc -c abr1.c -Wall
gcc abr1.o -o abr1

但是当我运行程序

./abr1 -f "result01.res"
zsh: bus error  ./abr1 -f "result01.res"

如何将文件名传递给这个C程序?

这是一个问题:

fname = (char *)malloc(200*sizeof(char));
fname = "abr.res";

你的malloc空间,fname指向,然后在下一行告诉fname指向字符串文字" &;这会造成内存泄漏,因为现在没有任何东西指向malloced内存。

此外,对于f选项,您可以使用strcpy来写入fname。修改字符串字面值是未定义行为,当然可以解释你看到的行为。

我推荐使用

char fname[200] = "abr.res";

这将fname创建为200字节长的可写内存区域,并将"abr.res"作为默认值初始化,并且不处理手动内存管理。

根据@Laci的注释,您很容易出现缓冲区溢出,盲目地将用户输入从命令行复制到您的缓冲区。应采取步骤消除这种风险。一种方法是使用strncpy:

case 'f':
strncpy(fname, optarg, sizeof fname);
// one of the dangers of strncpy is it is NOT guaranteed to NUL
// terminate the string, so do that manually just in case
fname[sizeof(fname)-1] = '';
break;

最新更新