意外与写

问题描述:

创造巨大的文件,这是我使用的代码:意外与写

#include <stdio.h> 
#include <stdlib.h> 
void main(){ 
    test = creat("TEST",0751); 
    close(test); 
    test = open("TEST",2); 
    write(test, "123456789101112131415",21); 
    lseek(test,-2,2); 
    read(test,swap_array,2); 
    write(test,swap_array,2); 
    lseek(test,-6, 1); 
    write(test,"xx",2); 
} 

这将创建一个包含而不是插入的数字之间的“XX”我打算一个8GB的文件。代码有什么问题,因为我拥有它?

+1

由于您不显示您的'#include's,我们无法知道范围内的原型是什么。请提供一个简短的**完整**程序,说明您遇到的错误。有关更多信息,请参见[mcve]。 –

+2

使用常量而不是幻数!为什么我们需要将它们翻译成任何有意义的东西? –

您未能包含适当的头文件。至少应包含以下内容:

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

此外,您还可以访问使代码可维护所需的符号常量。

这里是你的程序的工作版本:

#include <sys/types.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
#include <unistd.h> 


int main() { 
char swap_array[2]; 
int test = creat("TEST",0751); 
close(test); 
test = open("TEST",O_RDWR); 
write(test, "123456789101112131415",21); 
lseek(test,-2,SEEK_END); 
read(test,swap_array,2); 
write(test,swap_array,2); 
lseek(test,-6, SEEK_CUR); 
write(test,"xx",2); 
return 0; 
} 
+0

我也会替换'creat'的标志... –

+0

头文件解决了这个问题。我复制的旗帜严格为这个例子。 –

+0

@EugeneSh。 'creat()'的规范标志或'open()'的第三个参数非常详细:['S_IRWXU | S_IRGRP | S_IXGRP | S_IXOTH'](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_stat.h.html)为'0751'。阅读八进制比标准更容易。 –

你可能不包括头,所以有可能是没有原型的范围lseek(),所以中间参数的2int,但lseek()预计(一个long)的off_t,你是一个64位的机器,其中sizeof(int) != sizeof(long)所以两个2的是由系统调用误解的(也许他们当作偏移以任何理由还剩下些什么的堆栈是interp作为SEEK_SET或以其他方式跳至大偏移量)。

基本上,你很可能不准确传递信息输入到系统呼叫,因为您还没有正确的头。经典(POSIX干预前),中间22L因为lseek()l主张“长” - 在此之前,有一个seek()历时一个普通int(16位int类型的天数) - 到确保long通过lseek() 要求。这几天,lseek()需要off_t;使用原型对于确保您编写的内容正确解释为off_t至关重要。

有很多UB的潜伏在这样的描述,但你不使用SEEK_SET等事实提出了警告标志。另外,为什么该文件是可执行的?这看起来不像您正在编写的可执行代码。

代码的这种变体是更谨慎(并且不产生8吉布在Mac OS X 10.11.6文件,GCC 6.2.0)。

#include <fcntl.h> 
#include <sys/stat.h> 
#include <unistd.h> 

#define MODE_0751 (S_IRWXU | S_IRGRP | S_IXGRP | S_IXOTH) 

int main(void) 
{ 
    // All error checking omitted 
    char swap_array[2]; 
    int test = creat("TEST", MODE_0751); 
    close(test); 
    test = open("TEST", O_RDWR); 
    write(test, "123456789101112131415", 21); 
    lseek(test, -2L, SEEK_END); 
    read(test, swap_array, 2); 
    write(test, swap_array, 2); 
    lseek(test, -6L, SEEK_CUR); 
    write(test, "xx", 2); 
    close(test); 
    return 0; 
} 

我使用L的(非常)旧习惯,但它们是可选的。各种2可以替换为sizeof(swap_array)(和sizeof("xx")-1)。我在很久以前就学会了C,八进制许可是做生意的唯一途径; S_IRWXU和相关的名字是未来的几年。我发现一个4位或5位八进制数字比一串S_Iwxyz名称更易读。

确保您设定才可以使用函数原型所需的选项编译代码。例如,我使用:

$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes \ 
>  -Wstrict-prototypes -Wold-style-definition mx19.c -o mx19 
$ 
+0

'所以这两个2被处理......'我怀疑:AMD和MS ABI都会使用寄存器来传递x64上的前4个参数。 – Serge

+0

@Serge也许是i386。 – fuz

+0

从技术上讲,'lseek()'的第二个参数是'off_t',而不是'int'或'long'。 – EOF