【发布时间】:2021-08-14 06:17:16
【问题描述】:
我正在尝试用 C 编写一个基本的突变测试脚本,但我遇到了一些似乎无法解决的错误。首先要评论的是,在似乎有问题的函数中,namr,我尝试尝试使用简单的凯撒密码来命名我正在创建的文件,以避免在文件中包含不需要的字符姓名。当我按原样运行它时,似乎字符串 cexp 和 mcexp 有时会从我正在另一个函数 switchr中读取的文件中获取内容>。 当我在 Annotation 1 添加 printf 时,它似乎运行良好,但文件名出现错误。不过,如果我将注释 1 注释掉,则会出现 malloc(): 已损坏的顶部大小 错误。我尝试了各种打印,看看有什么问题。到注释 2 时,cexp 和 mcexp 仍然是所需的长度和内容,但到注释 3 时,它们是 26 或 25字符长,包括我在脚本其他部分读取的文件的起始行。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *namr(char *exp, char *mexp, int ignv) {
int explen = strlen(exp);
int mexplen = strlen(mexp);
//printf("EXPLEN: %d MEXPLEN: %d\n",explen,mexplen);
//ANNOTATION 1
char *cexp = (char *)malloc(explen + 1);
char *cmexp = (char *)malloc(mexplen + 1); //Exp in Caeser Cipher
for (int i = 0; i < explen; i++) {
cexp[i]= (exp[i] ? 'A' + exp[i] % 25 : exp[i]);
printf("%d - %c - %c\n", i, exp[i], 'A' + exp[i] % 25);
//ANNOTATION 2
}
for (int i = 0; i < mexplen; i++) {
cmexp[i]= (mexp[i] ? 'A' + mexp[i] % 25 : mexp[i]);
}
printf("EXP: %s\nMEXP: %s\n", exp, mexp);
printf("CEXP: %s\nCMEXP: %s\n", cexp, cmexp);
//ANNOTATION 3
printf("%s - %d\n%s - %d\n%d\n", cexp, strlen(cexp),
cmexp, strlen(cmexp), strlen("./U_SWITCH_MTNTS/TO%03.c"));
char *outname = (char *)malloc((30 + explen + mexplen));
sprintf(outname, "./U_SWITCH_MTNTS/%sTO%s%03d.c", cexp, cmexp, ignv);
free(cexp);
free(cmexp);
return outname;
}
int countr(char *filename, char *exp) {
int out = 0;
int i, flag;
int inlen = strlen(exp);
char c;
FILE *f = fopen(filename, "r");
while (c != EOF) {
for (i = 0, flag = 0; i < inlen; i++) {
if (exp[i] != c) {
flag = 1;
break;
}
c = getc(f);
}
if (flag == 0)
out++;
c = getc(f);
}
fclose(f);
return out;
}
char *switchr(char *filename, char *exp, char *mexp, int ignv) {
int i, flag,buffcount;
FILE *f = fopen(filename, "r");
char *outname = namr(exp, mexp, ignv);
FILE *fout = fopen(outname, "w");
char c = getc(f);
int ignc = ignv;
int inlen = strlen(exp);
char *buffer = (char *)malloc(inlen * sizeof(char));
while (c != EOF) {
for (i = 0, flag = 0, buffcount = 0; i < inlen; i++) {
if (exp[i] != c) {
flag = 1;
break;
} else {
buffer[buffcount] = c;
buffcount++;
c = getc(f);
}
}
if (flag == 0) {
if(ignc == 0) {
fputs(mexp, fout);
} else {
for (i = 0; i < buffcount; i++)
fputc(buffer[i], fout);
}
ignc--;
} else {
for (i = 0; i < buffcount; i++)
fputc(buffer[i], fout);
}
fputc(c, fout);
c = getc(f);
}
fclose(f);
fclose(fout);
return outname;
}
void mstrswitch(char *filename) {
int ecount = countr(filename, "==");
char **filenames = (char **)malloc(5 * ecount * sizeof(char *));
char command[100];
system("mkdir U_SWITCH_MTNTS");
system("mkdir TEST_OBJECTS");
for (int i = 0;i < ecount; i++) {
filenames[5 * i] = switchr("test.c", "==", "<=", i);
filenames[5 * i + 1] = switchr("test.c", "==", ">=", i);
filenames[5 * i + 2] = switchr("test.c", "==", ">", i);
filenames[5 * i + 3] = switchr("test.c", "==", "<", i);
filenames[5 * i + 4] = switchr("test.c", "==", "!=", i);
}
for (int i = 0; i < 5 * ecount; i++) {
sprintf(command, "gcc -o ./TEST_OBJECTS/test%03d %s", i, filenames[i]);
system(command);
sprintf(command, "./TEST_OBJECTS/test%03d", i);
system(command);
free(filenames[i]);
}
free(filenames);
}
int main() {
mstrswitch("test.c");
return 0;
}
【问题讨论】:
-
通过 valgrind 运行您的代码。如果你对内存管理不善,它会告诉你在哪里。
-
sizeof(char *)*5*ecount比5*ecount*sizeof(char *)有一个优势:不太可能溢出。 -
@chux-ReinstateMonica:是吗?重新排序表达式中的术语如何改变溢出的可能性?
-
@JonathanLeffler
(size_t)*(int)*(int)执行 2 个size_t * size_t乘法。(int)*(int)*(size_t)执行 1 个int*int和 1 个size_t * size_t乘法。由于size_t的正值范围绝大多数都比int更宽,因此溢出的机会更少。 -
@chux-ReinstateMonica:好的——我知道你来自哪里。我不相信编译器不能重新排列操作顺序,但你的建议可能会避免麻烦。