我正在尝试在“批处理文件模式”上实现自定义外壳程序。假设我有一个名为“ batchfile”的文件,其中包含:
ls –l
pwd
ps
touch hello
ls -l ; cat file ; grep foo file2
ls -l && cat file
quit
调用./myShell batchfile
,我想分别执行命令。但是,当我尝试使用fgets()
从文件中读取行,然后将它们存储到数组(char * batch_cmds[512]
)中时,我得到了:
分段错误(核心已转储)
到目前为止,这是我的代码:
int main(int argc, char *argv[]){
if (argc >=2){
char str[512];
char *batch_cmds[512];
int i=0;
FILE *fp;
fp = fopen(argv[1], "r");
while(fgets(str,512, fp)!=NULL){
strcpy(batch_cmds[i], str);
i++;
}
fclose(fp);
我不明白为什么会弹出此错误。
答案 0 :(得分:4)
您为指针本身保留了空间,但没有为每个此类指针指向的字符串保留空间。每个batch_cmds[i]
都指向“某处”,至少不是指向您分配的对象。然后,当您调用strcpy(batch_cmds[i], str);
时,会将str
的内容写到“某处”并产生未定义的行为(例如,崩溃;实际上,语句batch_cmds[i]
访问未初始化的数组,并且本身已经是未定义的)行为;但仅此一项很少会导致崩溃。
代替
strcpy(batch_cmds[i], str);
写
batch_cmds[i] = strdup(str);
命令strdup
既执行以下操作-(1)保留足够大的内存以容纳str
的内容,以及(2)然后复制str
的内容。这等效于batch_cmds[i] = malloc(strlen(str)+1); strcpy(batch_cmds[i], str));
。
另外,检查i
是否为<512
,以使batch_cmds[i]
不会超出数组范围。
答案 1 :(得分:1)
该行:
char *batch_cmds[512];
声明一个指向char
的512个指针的数组,但是这些指针尚未初始化(野生,晃晃,任您选择)。
您的选择:
在堆栈上声明2D数组:
char batch_cmds[512][512];
使用动态内存管理在堆上分配字符串:
char *batch_cmds[512];
int i;
for(i = 0; i < 512; i++)
{
batch_cmds[i] = malloc(string_length);
if(batch_cmds[i] == NULL)
{
// handle alloc error
}
}
// Code that uses batch_cmds...
for(i = 0; i < 512; i++)
{
free(batch_cmds[i]);
batch_cmds[i] = NULL;
}
使用strdup
分配给char
中batch_cmds
的指针(在斯蒂芬·莱希纳的答案中演示)。请注意,strdup
还在后台使用堆内存,因此在完成处理操作后,还必须将返回的指针传递给free
,以避免内存泄漏。