在代码中,我尝试读取一个文件,然后将其与strtok分开,以获取目录的ID(由8个字符组成)以及要传递给目录的文件类型(A,B,C。 pdf)。然后,我使用功能系统执行相应的命令。我知道在txt文件中,它首先出现的是目录的ID,然后是文件的类型。我的编译没有任何问题,但是当我执行程序时,出现了分段错误,我也不知道为什么。
#include <stdio.h>
#include <stdlib.h>
#define _GNU_SOURCE
#include <unistd.h>
#include <ctype.h>
#include <stdbool.h>
#include <string.h>
int main(int argc, char* argv[]){
char ch, str[999], id[8], command[25];
FILE *fp;
int i = 0;
char *pch;
fp = fopen("p1.text", "r");
if (fp == NULL)
{
perror("Error while opening the file.\n");
exit(EXIT_FAILURE);
}
while((ch = fgetc(fp)) != EOF){
str[i] = ch;
i++;
}
pch = strtok(str, " ,.-\n");
while(pch != NULL){
if(isalpha(pch)){
sprintf(command, "cp %s.pdf %s", pch, id);
system(command);
strcpy(command, "");
}
if(strlen(pch) == 8){
strcpy(id, pch);
}
pch = strtok(NULL, " ,.-\n");
}
fclose(fp);
return 0;
}
答案 0 :(得分:1)
id
变量不足以容纳它需要存储的值。
C中的字符串以null终止。因此,一个8字符串需要9字节的存储空间。 id
只有8个元素,因此,当您将其复制到数组的末尾时,将其写入。在数组边界之外进行写操作会调用undefined behavior,在这种情况下,这会导致代码崩溃。
将id
的长度设为8而不是8:
int id[9];
您还没有正确存储fgetc
的结果。您将ch
声明为char
,但是fgetc
返回int
。要将EOF
与普通字符值区分开来是必需的。因此,将ch
的类型更改为int
。
此外,通过一次读取整个文件,然后在循环中使用内部状态机来调用strtok
来弄清楚您要使用的元素,这使事情变得比需要复杂的多阅读。
您可以使用fgets
一次读一行,然后调用strtok
一次以获得id
,再调用一次pch
来简化此操作:>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char line[100], command[100];
FILE *fp;
char *pch, *id;
fp = fopen("p1.text", "r");
if (fp == NULL)
{
perror("Error while opening the file.\n");
exit(EXIT_FAILURE);
}
while (fgets(line, sizeof(line), fp)) {
id = strtok(line, " \n");
if (!id) continue;
pch = strtok(NULL, " \n");
if (!pch) continue;
snprintf(command, sizeof(command), "cp %s.pdf %s", pch, id);
//printf("command=%s\n", command);
system(command);
}
fclose(fp);
return 0;
}
答案 1 :(得分:0)
我将向您展示一个调试过程,您应该学习该过程,以便自己解决这些问题。我采取的步骤如下所示。请注意,我并不是在尝试解决您的代码中的所有可能问题。我只是隔离并解决了最初的问题。
您应该熟悉gdb
和valigrind
之类的调试工具。有时,在调试器下运行可执行文件会使问题“消失”。在这种情况下,诸如valgrind
之类的内存访问检查工具非常有用。
我用valgrind
运行了您的代码,它给了我以下输出:
在运行valgrind
之前,应使用调试符号构建可执行文件。假设您使用的是gcc,请按照以下步骤操作。
jnorton@ubuntu:~/source$ gcc -ggdb fault.c jnorton@ubuntu:~/source$ ./a.out pch = this Segmentation fault (core dumped) jnorton@ubuntu:~/source$ clear jnorton@ubuntu:~/source$ gcc -ggdb fault.c jnorton@ubuntu:~/source$ valgrind --leak-check=yes ./a.out ==6745== Memcheck, a memory error detector ==6745== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==6745== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info ==6745== Command: ./a.out ==6745== pch = this ==6745== Invalid read of size 2 ==6745== at 0x108B25: main (fault.c:35) ==6745== Address 0x2fda2c0 is not stack'd, malloc'd or (recently) free'd ==6745== ==6745== ==6745== Process terminating with default action of signal 11 (SIGSEGV) ==6745== Access not within mapped region at address 0x2FDA2C0 ==6745== at 0x108B25: main (fault.c:35) ==6745== If you believe this happened as a result of a stack ==6745== overflow in your program's main thread (unlikely but ==6745== possible), you can try to increase the size of the ==6745== main thread stack using the --main-stacksize= flag. ==6745== The main thread stack size used in this run was 8388608. ==6745== ==6745== HEAP SUMMARY: ==6745== in use at exit: 552 bytes in 1 blocks ==6745== total heap usage: 3 allocs, 2 frees, 5,672 bytes allocated ==6745== ==6745== LEAK SUMMARY: ==6745== definitely lost: 0 bytes in 0 blocks ==6745== indirectly lost: 0 bytes in 0 blocks ==6745== possibly lost: 0 bytes in 0 blocks ==6745== still reachable: 552 bytes in 1 blocks ==6745== suppressed: 0 bytes in 0 blocks ==6745== Reachable blocks (those to which a pointer was found) are not shown. ==6745== To see them, rerun with: --leak-check=full --show-leak-kinds=all ==6745== ==6745== For counts of detected and suppressed errors, rerun with: -v ==6745== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0) Segmentation fault (core dumped) jnorton@ubuntu:~/source$
valgrind
通知已报告:
==6745== at 0x108B25: main (fault.c:35)
我添加了一些调试printfs,但第35行是:
if(isalpha(pch)){
此处发生segfault
是因为isalpha()
接受一个int
参数,而不是指向字符串的指针。将该行更改为以下行将停止segfault
:
if(isalpha((int)pch[0])){
现在,这只是代码中的一个问题。您可能还有其他问题。