2010-10-05 32 views
0

Je n'arrive pas à déboguer ce code. J'ai copié l'exemple d'un guide, ce fichier est-il incorrectement indexé?Quel est le problème avec ces appels système?

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

char *inicio(void); 

main(void) 
{ 
    char *c; 
    int fd, sz, i;  
    c = inicio(); 

    fd = open("input.in", O_RDONLY); 
    if (fd < 0) { perror("r1"); exit(1); } 

    sz = read(fd, c, 10); 
    printf("We have opened input.in, and have called read(%d, c, 10).\n", fd); 
    printf("read has read %d bytes.\n", sz); 
    printf("The bytes are these: %s\n", c); 

    i = lseek(fd, 0, SEEK_CUR); 
    printf("lseek(%d, 0, SEEK_CUR) returns the current location on the file being %d\n\n", fd, i); 

    printf("We now look for the start of the file and call read(%d, c, 10)\n",fd); 
    lseek(fd, 0, SEEK_SET); 
    sz = read(fd, c, 10); 

    printf("The reading returns the following bytes: %s\n", c); 

    printf("We now execute lseek(%d, -6, SEEK_END). and return %d\n",fd, (int) lseek(fd, -6, SEEK_END)); 
    printf("Executing read(%d, c, 10), we get the following bytes: ", fd); 

    sz = read(fd, c, 10); 

    printf("Finally, we execute lseek(%d, -1, SEEK_SET). This returns -1.\n", fd); 
    printf("perror() indicates the fault:\n"); 
    fflush(stdout); 

    i = lseek(fd, -1, SEEK_SET); 
    perror("l1"); 
} 

char *inicio(void) 
{ 
    char *bytes; 
    int j; 
    bytes = (char *) calloc(100, sizeof(char)); 
    for(j=0;j<100;j++){bytes[j]=rand()%32+1;} 
    return bytes; 
} 

le fichier d'entrée est:

Jim Plank 
Claxton 221 
+0

Peut-être pourriez-vous nous montrer la production produite. Et l'entrée - _input.in_ contient-elle réellement 16 caractères? –

+0

Bien sûr, je l'ai manqué. Maintenant, c'est ajouté. – andandandand

+1

Vous demandez "ce qui ne va pas", sans nous donner la moindre idée des symptômes. Qu'est-ce qui se passe réellement? –

Répondre

3

Si vous recherchez un décalage négatif par rapport au début du fichier, vous obtenez une erreur - il n'y a pas d'octets accessibles avant le début du fichier.

De même, vous devez toujours vérifier ou capturer les résultats des appels système, plutôt que de vous baser sur errno. La bibliothèque C ne définit jamais errno à zéro (autre que lorsque le processus/thread démarre). Il peut être défini sur une valeur non nulle même si la fonction a réussi. Sous Solaris, il est courant que errno soit défini après l'écriture dans un fichier car le fichier n'est pas un terminal et la bibliothèque tente une opération qui ne réussit que sur un terminal.


Code de travail, moins l'allocation de mémoire via 'malloc()'. Il n'imprime explicitement que le nombre de caractères lus ('<<%.*s>>' limite la longueur à la taille donnée, les crochets permettent de voir facilement les données en cours d'impression).

#include <unistd.h> 
#include <fcntl.h> 
#include <stdio.h> 
#include <stdlib.h> 

int main(void) 
{ 
    char c[100]; 
    int fd, sz, i; 

    fd = open("input.in", O_RDONLY); 
    if (fd < 0) 
    { 
     perror("Error from open(\"input.in\", O_RDONLY)"); 
     exit(1); 
    } 

    sz = read(fd, c, 10); 
    printf("Opened input.in (fd = %d)\n", fd); 
    printf("We called read(fd, c, 10) and read %d bytes: <<%.*s>>\n", 
      sz, sz, c); 

    i = lseek(fd, 0, SEEK_CUR); 
    printf("lseek(fd, 0, SEEK_CUR) returns the current offset of %d\n", i); 

    printf("We seek to start of the file and call read(fd, c, 10)\n"); 
    i = lseek(fd, 0, SEEK_SET); 
    if (i != 0) 
     perror("Error from lseek(fd, 0, SEEK_SET)\n"); 

    sz = read(fd, c, 10); 
    if (sz < 0) 
     perror("Error from read(fd, c, 10)\n"); 
    printf("We read the following bytes: <<%.*s>>\n", sz, c); 

    printf("We now execute lseek(fd, -6, SEEK_END) which returns %d\n", 
      (int) lseek(fd, -6, SEEK_END)); 
    printf("Executing read(fd, c, 10), we get the following bytes: "); 

    sz = read(fd, c, 10); 
    if (sz < 0) 
     perror("Error from read(fd, c, 10)\n"); 
    printf("<<%.*s>>\n", sz, c); 

    printf("Finally, we execute lseek(fd, -1, SEEK_SET) which returns -1\n"); 
    fflush(stdout); 

    if ((i = lseek(fd, -1, SEEK_SET)) < 0) 
     perror("Error from lseek(fd, -1, SEEK_SET)"); 
    printf("i = %d\n", i); 
    return 0; 
} 

Sortie:

Opened input.in (fd = 3) 
We called read(fd, c, 10) and read 10 bytes: <<Jim Plank 
>> 
lseek(fd, 0, SEEK_CUR) returns the current offset of 10 
We seek to start of the file and call read(fd, c, 10) 
We read the following bytes: <<Jim Plank 
>> 
We now execute lseek(fd, -6, SEEK_END) which returns 16 
Executing read(fd, c, 10), we get the following bytes: <<n 221 
>> 
Finally, we execute lseek(fd, -1, SEEK_SET) which returns -1 
Error from lseek(fd, -1, SEEK_SET): Invalid argument 
i = -1 
+0

J'ai copié ce décalage à partir d'un guide. J'ai changé chaque négatif pour un positif et j'ai obtenu une erreur de segmentation, quelle est la bonne façon d'indexer ici? – andandandand

+1

@omgzor: Je ne suis pas sûr de ce que vous voulez dire - vous ne pouvez pas changer les signes sur tout et s'attendre à ce que cela fonctionne. Chercher 6 au-delà de la fin d'un fichier en lecture seule ne va généralement pas beaucoup aider, par exemple. J'ai mis à jour la réponse avec du code qui ne s'écrase pas. –

+0

Désolé, j'ai mal compris l'utilisation de l'offset. J'ai changé le dernier lseek en i = lseek (fd, 0, SEEK_SET) en fonction de votre réponse et j'ai obtenu ce que je voulais. Merci. – andandandand

1

printf("The bytes are these: %s\n", c);

violation d'accès (garanti un). Vous n'avez pas de terminateur '\0'.

va de même pour:

printf("The reading returns the following bytes: %s\n", c);

+0

Où le terminateur doit-il être placé? Sur le fichier lu? Je ne suis pas habitué à C et à ses erreurs de mémoire. – andandandand

+0

'c [sz] = '\ 0';' après les appels lus. –

+0

Ceci est un problème valide avec le code - ce n'est pas une explication de l'échec du dernier 'lseek()'. –

1

Que voulez-vous attendre à la position -1th du fichier? Peut-être que vous vouliez SEEK_CUR ou SEEK_END au lieu de SEEK_SET.

-1
c[sz] = '\0'; 

après les appels de lecture.