C 使用read()和write()的分段错误(堆芯转储)

C 使用read()和write()的分段错误(堆芯转储),c,C,我已经退出C语言编程将近两年了,最近在学校得到了一个关于使用write()和read()的作业 在代码的某个地方,我收到了分段错误,可能是在filecopy函数上,这是我投入资金的地方。我试过GDB,但自从上次用C编程以来我就没用过它,所以我转到这里 密码 #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <unistd.h> #include <fc

我已经退出C语言编程将近两年了,最近在学校得到了一个关于使用write()和read()的作业

在代码的某个地方,我收到了分段错误,可能是在filecopy函数上,这是我投入资金的地方。我试过GDB,但自从上次用C编程以来我就没用过它,所以我转到这里

密码

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>

int main(int argc, char *argv[]) {

void filecopy(int infd, int outfd);

int fd = -1;
char *prog = argv[0];
if(argc == 1) 
    filecopy(STDIN_FILENO, STDOUT_FILENO);
else 
    while(--argc > 0) {
        if((fd = open(*++argv, O_RDONLY, "rb")) == -1) {
            // we don't have fprintf... but we have sprintf =]
            char tmp[30];
            sprintf(tmp, "%s: can't open %s\0", prog, *argv);
            write(STDOUT_FILENO, &tmp, sizeof(tmp));    
            exit(-1);
        } else {
            filecopy(fd, STDOUT_FILENO); 
            close(fd);  
        }
    }
exit(0);

}

void filecopy(int infd, int outfd) {
    // char *buf[1]; <-- causes unreadable characters outputted by write
    char *buf;
    while(read(infd, buf, 1) != -1) 
        write(outfd, buf, sizeof(buf));
}
#包括
#包括
#包括
#包括
#包括
int main(int argc,char*argv[]){
无效文件副本(输入、输出);
int-fd=-1;
char*prog=argv[0];
如果(argc==1)
文件副本(标准文件号、标准文件号);
其他的
而(--argc>0){
如果((fd=open(*++argv,orduonly,“rb”))=-1){
//我们没有fprintf…但是我们有sprintf=]
char-tmp[30];
sprintf(tmp,“%s:无法打开%s\0”,prog,*argv);
写入(STDOUT_FILENO,&tmp,sizeof(tmp));
出口(-1);
}否则{
文件副本(fd、STDOU文件号);
关闭(fd);
}
}
出口(0);
}
无效文件副本(int infd,int outfd){

//char*buf[1];
char*buf;
是一个未初始化的指针,通过该指针写入数据是无效的 未定义的行为

char buf[1024];

ssize_t len;

while((len = read(infd, buf, sizeof buf)) != -1)
    write(outfd, buf, len);
这是正确的

请注意,
char*buf[1];
指针的数组(维度为1),即
与
char
s数组不同。使用该数组需要执行以下操作
read(infd,buf[0],somelength)
,但这里的
buf[0]
将是一个 如果指针未初始化,您也会遇到同样的问题。这就是为什么要声明 例如1024的
char
数组(您可以选择其他大小)是正确的 去做

也主要用于strlen(tmp)
和非
sizeof(tmp)

strlen
返回字符串的长度,该长度可能小于29,并且 如果使用
sizeof(tmp)
,则可能会在结束后写入垃圾 请注意,对于整个字符串,0可能太小,我会使用 较大的数字或使用
snprintf
构造字符串:

snprintf(tmp, sizeof tmp, "%s: can't open %s\0", prog, *argv);
这样会更安全

最后一件事:

while(--argc > 0)
    if((fd = open(*++argv, O_RDONLY, "rb")) == -1) {
        ...
虽然这是正确的,但我觉得这段代码很难理解 如果您这样做,阅读起来就会简单得多:

for(int i = 1; i < argc; ++i)
    if((fd = open(argv[i], O_RDONLY, "rb")) == -1) {
        ...
[……]

mode参数指定创建新文件时应用的文件模式位。必须在
O_create
O_TMPFILE
标志中指定;如果既不指定
O_create
也不指定
O_TMPFILE
,则忽略模式。 有效模式由进程的
umask
以通常方式修改:在没有默认
ACL
的情况下,创建文件的模式为
(mode&~umask)
。请注意,此模式仅适用于将来访问新创建的文件;创建 只读文件可能会返回一个读/写文件描述符

为模式提供以下符号常量:

S_IRWXU
00700
用户(文件所有者)具有读取、写入和执行权限

S\u IRUSR
00400
用户具有读取权限

S_IWUSR
00200
用户具有写入权限

S_IXUSR
00100
用户具有执行权限

[……]

由于您既不使用
O_create
也不使用
O_TMPFILE
,因此此参数将 忽略并将
char*
作为
mode\u t
传递,该模式本质上是整数。 因此,您的电话应该是:

    if((fd = open(argv[i], O_RDONLY, 0)) == -1) {
        ...

char*buf;
是未初始化的指针,通过该指针写入数据是无效的 未定义的行为

char buf[1024];

ssize_t len;

while((len = read(infd, buf, sizeof buf)) != -1)
    write(outfd, buf, len);
这是正确的

请注意,
char*buf[1];
指针的数组(维度为1),即
与
char
s数组不同。使用该数组需要执行以下操作
read(infd,buf[0],somelength)
,但这里的
buf[0]
将是一个 如果指针未初始化,您也会遇到同样的问题。这就是为什么要声明 例如1024的
char
数组(您可以选择其他大小)是正确的 去做

也主要用于strlen(tmp)
和非
sizeof(tmp)

strlen
返回字符串的长度,该长度可能小于29,并且 如果使用
sizeof(tmp)
,则可能会在结束后写入垃圾 请注意,对于整个字符串,0可能太小,我会使用 较大的数字或使用
snprintf
构造字符串:

snprintf(tmp, sizeof tmp, "%s: can't open %s\0", prog, *argv);
这样会更安全

最后一件事:

while(--argc > 0)
    if((fd = open(*++argv, O_RDONLY, "rb")) == -1) {
        ...
虽然这是正确的,但我觉得这段代码很难理解 如果您这样做,阅读起来就会简单得多:

for(int i = 1; i < argc; ++i)
    if((fd = open(argv[i], O_RDONLY, "rb")) == -1) {
        ...
[……]

mode参数指定创建新文件时应用的文件模式位。必须在
O_create
O_TMPFILE
标志中指定;如果既不指定
O_create
也不指定
O_TMPFILE
,则忽略模式。 有效模式由进程的
umask
以通常方式修改:在没有默认
ACL
的情况下,创建文件的模式为
(mode&~umask)
。请注意,此模式仅适用于将来访问新创建的文件;创建 只读文件可能会返回一个读/写文件描述符

为模式提供以下符号常量:

S_IRWXU
00700
用户(文件所有者)具有读取、写入和执行权限

S\u IRUSR
00400
用户具有读取权限

S_IWUSR
00200
用户具有写入权限

S_IXUSR
00100
us