zsh:传递结果文件名编译 C 程序时出现总线错误
zsh: bus error when passing results filename to compile C program
在下面的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 filename\n";
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("-h\tHelp\n", stdout);
fputs("-u\tLower threshold (cells)\n", stdout);
fputs("-U\tUpper threshold (cells)\n", stdout);
fputs("-d\tDecrement factor\n", stdout);
fputs("-i\tIncrement factor\n", stdout);
fputs("-p\tPeak cell rate (Mbps)\n", stdout);
fputs("-T\tActualization period (cells)\n", stdout);
fputs("-f\tResults file name\n", 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, "%d\t", 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.1f\t%4.1f\t", ACR[i]/1E6, mean[i]/1E6);
}
qlen += (int)(ACRacc*T*424/PCR);
qlen = (qlen<=T*424)?(0):(qlen - T*424);
fprintf(filefd, "%d\n", 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
space fname
指向,然后在下一行告诉 fname
指向字符串文字“abr.res”。这会造成内存泄漏,因为您现在没有任何东西指向您的 malloc
ed 内存。
此外,使用 f
选项,您可以使用 strcpy
写入 fname
。 Modifying a string literal is Undefined Behavior,当然可以解释您所看到的行为。
相反,我推荐
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] = '[=12=]';
break;
在下面的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 filename\n";
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("-h\tHelp\n", stdout);
fputs("-u\tLower threshold (cells)\n", stdout);
fputs("-U\tUpper threshold (cells)\n", stdout);
fputs("-d\tDecrement factor\n", stdout);
fputs("-i\tIncrement factor\n", stdout);
fputs("-p\tPeak cell rate (Mbps)\n", stdout);
fputs("-T\tActualization period (cells)\n", stdout);
fputs("-f\tResults file name\n", 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, "%d\t", 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.1f\t%4.1f\t", ACR[i]/1E6, mean[i]/1E6);
}
qlen += (int)(ACRacc*T*424/PCR);
qlen = (qlen<=T*424)?(0):(qlen - T*424);
fprintf(filefd, "%d\n", 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
space fname
指向,然后在下一行告诉 fname
指向字符串文字“abr.res”。这会造成内存泄漏,因为您现在没有任何东西指向您的 malloc
ed 内存。
此外,使用 f
选项,您可以使用 strcpy
写入 fname
。 Modifying a string literal is Undefined Behavior,当然可以解释您所看到的行为。
相反,我推荐
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] = '[=12=]';
break;