Segmentation error with getline() function?












-1















I'm learning C on the terminal on Linux, and I did a small game in text, so everything is functioning (especially my big loop for if the player want to restart the game), and I just add a dump "Enter your pseudo" at the beginning.



It doesn't function when I enter it, it says me



Segmentation Error , core dumped


Here is all the code, the most important is the first lines because all the rest is functioning perfectly:



#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdbool.h>
int main (void) {
// déclaration des variables
bool essais8 = false ;
bool essais10 = false ;
bool essais12 = false;
bool essais14 = false;
bool condition = true;
bool condition_diff = false;
bool condition_recommencer = false;
bool condition_bonus1 = true;
bool condition_bonus2 = true;
bool condition_bonus3 = true;
char* buffer;
char* recommencer;
char* pseudo ;
size_t bufsize = 32;
size_t characters;
int difficulte;
int sheitan = 0;
int sheitan2 = 0;
int a;
int bonus1;
int bonus2;
int bonus3;
int ecart;
int essais;
int nb_bonus2;
srand(time(NULL));




// on récupère le pseudo du joueur
printf("Salut ! Quel est ton nom ? ");
characters = getline(&buffer,&bufsize,stdin);
pseudo = buffer;
// after this I have the segmentation errror




while (condition == true) { // Boucle de recommencement du Jeu
// here is the big game that was functioning perfectly before I add the pseudo option on top.
}
printf("Fin du programme n");
return(0);
}









share|improve this question




















  • 2





    None of your pointers are initialized to point at valid memory

    – UnholySheep
    Jan 19 at 11:10






  • 2





    @UnholySheep ... or NULL or 0.

    – alk
    Jan 19 at 11:11


















-1















I'm learning C on the terminal on Linux, and I did a small game in text, so everything is functioning (especially my big loop for if the player want to restart the game), and I just add a dump "Enter your pseudo" at the beginning.



It doesn't function when I enter it, it says me



Segmentation Error , core dumped


Here is all the code, the most important is the first lines because all the rest is functioning perfectly:



#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdbool.h>
int main (void) {
// déclaration des variables
bool essais8 = false ;
bool essais10 = false ;
bool essais12 = false;
bool essais14 = false;
bool condition = true;
bool condition_diff = false;
bool condition_recommencer = false;
bool condition_bonus1 = true;
bool condition_bonus2 = true;
bool condition_bonus3 = true;
char* buffer;
char* recommencer;
char* pseudo ;
size_t bufsize = 32;
size_t characters;
int difficulte;
int sheitan = 0;
int sheitan2 = 0;
int a;
int bonus1;
int bonus2;
int bonus3;
int ecart;
int essais;
int nb_bonus2;
srand(time(NULL));




// on récupère le pseudo du joueur
printf("Salut ! Quel est ton nom ? ");
characters = getline(&buffer,&bufsize,stdin);
pseudo = buffer;
// after this I have the segmentation errror




while (condition == true) { // Boucle de recommencement du Jeu
// here is the big game that was functioning perfectly before I add the pseudo option on top.
}
printf("Fin du programme n");
return(0);
}









share|improve this question




















  • 2





    None of your pointers are initialized to point at valid memory

    – UnholySheep
    Jan 19 at 11:10






  • 2





    @UnholySheep ... or NULL or 0.

    – alk
    Jan 19 at 11:11
















-1












-1








-1








I'm learning C on the terminal on Linux, and I did a small game in text, so everything is functioning (especially my big loop for if the player want to restart the game), and I just add a dump "Enter your pseudo" at the beginning.



It doesn't function when I enter it, it says me



Segmentation Error , core dumped


Here is all the code, the most important is the first lines because all the rest is functioning perfectly:



#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdbool.h>
int main (void) {
// déclaration des variables
bool essais8 = false ;
bool essais10 = false ;
bool essais12 = false;
bool essais14 = false;
bool condition = true;
bool condition_diff = false;
bool condition_recommencer = false;
bool condition_bonus1 = true;
bool condition_bonus2 = true;
bool condition_bonus3 = true;
char* buffer;
char* recommencer;
char* pseudo ;
size_t bufsize = 32;
size_t characters;
int difficulte;
int sheitan = 0;
int sheitan2 = 0;
int a;
int bonus1;
int bonus2;
int bonus3;
int ecart;
int essais;
int nb_bonus2;
srand(time(NULL));




// on récupère le pseudo du joueur
printf("Salut ! Quel est ton nom ? ");
characters = getline(&buffer,&bufsize,stdin);
pseudo = buffer;
// after this I have the segmentation errror




while (condition == true) { // Boucle de recommencement du Jeu
// here is the big game that was functioning perfectly before I add the pseudo option on top.
}
printf("Fin du programme n");
return(0);
}









share|improve this question
















I'm learning C on the terminal on Linux, and I did a small game in text, so everything is functioning (especially my big loop for if the player want to restart the game), and I just add a dump "Enter your pseudo" at the beginning.



It doesn't function when I enter it, it says me



Segmentation Error , core dumped


Here is all the code, the most important is the first lines because all the rest is functioning perfectly:



#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdbool.h>
int main (void) {
// déclaration des variables
bool essais8 = false ;
bool essais10 = false ;
bool essais12 = false;
bool essais14 = false;
bool condition = true;
bool condition_diff = false;
bool condition_recommencer = false;
bool condition_bonus1 = true;
bool condition_bonus2 = true;
bool condition_bonus3 = true;
char* buffer;
char* recommencer;
char* pseudo ;
size_t bufsize = 32;
size_t characters;
int difficulte;
int sheitan = 0;
int sheitan2 = 0;
int a;
int bonus1;
int bonus2;
int bonus3;
int ecart;
int essais;
int nb_bonus2;
srand(time(NULL));




// on récupère le pseudo du joueur
printf("Salut ! Quel est ton nom ? ");
characters = getline(&buffer,&bufsize,stdin);
pseudo = buffer;
// after this I have the segmentation errror




while (condition == true) { // Boucle de recommencement du Jeu
// here is the big game that was functioning perfectly before I add the pseudo option on top.
}
printf("Fin du programme n");
return(0);
}






c linux getline






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jan 19 at 11:23









alk

58.6k763172




58.6k763172










asked Jan 19 at 11:07









ChetritChetrit

31




31








  • 2





    None of your pointers are initialized to point at valid memory

    – UnholySheep
    Jan 19 at 11:10






  • 2





    @UnholySheep ... or NULL or 0.

    – alk
    Jan 19 at 11:11
















  • 2





    None of your pointers are initialized to point at valid memory

    – UnholySheep
    Jan 19 at 11:10






  • 2





    @UnholySheep ... or NULL or 0.

    – alk
    Jan 19 at 11:11










2




2





None of your pointers are initialized to point at valid memory

– UnholySheep
Jan 19 at 11:10





None of your pointers are initialized to point at valid memory

– UnholySheep
Jan 19 at 11:10




2




2





@UnholySheep ... or NULL or 0.

– alk
Jan 19 at 11:11







@UnholySheep ... or NULL or 0.

– alk
Jan 19 at 11:11














4 Answers
4






active

oldest

votes


















2














You forgot to initialize buffer. And you'll better end your printf(3) format control string with n or else call fflush(3) before any input (since stdio(3) is buffered).



An uninitialized pointer contains garbage. Using it is undefined behavior. Be scared !



So my suggestion is to code



size_t bufsiz = 64;
char *buffer = malloc(bufsiz);
if (!buffer) { perror("malloc buffer"); exit(EXIT_FAILURE); };


and later



printf("Salut ! Quel est ton nom ?n");
characters = getline(&buffer,&bufsize,stdin);


Next time enable all warnings and debug info when compiling, so compile your code with gcc -Wall -Wextra -g if using GCC. You would have got some warnings.



Of course, read How to debug small programs and debugging with GDB



On Linux, in your particular case, you could be interested in using readline(3) instead of getline(3).



Don't forget to read the documentation of every function that you are using (e.g. here, if it is a standard C one).






share|improve this answer


























  • Thank you It worked! but if my buffer wasn't poiting any memory , why does it did work with all my program and never had this error ?

    – Chetrit
    Jan 19 at 11:19











  • Follow all the links I am giving in my answer

    – Basile Starynkevitch
    Jan 19 at 11:21











  • Thank you very much ! Have a great day !

    – Chetrit
    Jan 19 at 11:29



















2














getline() can be used in two different ways:




  1. Read into a buffer provided by the caller.

  2. Allocate memory when reading.


To use 1. initialise the pointer passed to point to valid memory and pass as well the size of the latter.



#define INITIAL_SIZE (42)

int main(void)
{
char * buffer = malloc(INITIAL_SIZE * sizeof *buffer);
size_t bufsize = INITIAL_SIZE;
ssize_t characters = getline(&buffer, &bufsize, stdin);
if (-1 == characters)
{
/* handle error. */
}
else
{
/* use buffer */
}

free(buffer); /* Free buffer. */
}


To use 2. initialise the pointer passed to NULL and pass 0 as size.



int main(void)
{
char * buffer = NULL;
size_t bufsize = 0;
ssize_t characters = getline(&buffer, &bufsize, stdin);
if (-1 == characters)
{
/* handle error. */
}
else
{
/* use buffer */
}

free(buffer); /* Free buffer. */
}


Note: getline() returns ssize_t not size_t.






share|improve this answer


























  • Outsh! @NominalAnimal Fixed! Thx! :}

    – alk
    Jan 19 at 13:32





















1














'buffer' variable is pointing to some garbage memory address. You need to allocate necessary memory first, using 'malloc' function or make 'buffer' a static array, instead of pointer.






share|improve this answer



















  • 1





    "You need to allocate [...] memory first" not necessarily. Please see my answer of an alternative to use getline().

    – alk
    Jan 19 at 11:21



















0














getline() is a POSIX.1 function, which reads lines into dynamically allocated buffers, allowing lines of any length (limited only by the amount of available memory). It returns the number of characters read, or -1 if there is no more input, or an error occurred.



Here is one example use pattern:



    char   *line = NULL;
size_t size = 0;
ssize_t len;

while (1) {

len = getline(&line, &size, stdin);
if (len < 1)
break;

/* Do something with the input line */

}


At any point, you can release the dynamically allocated buffer using



    free(line);
line = NULL;
size = 0;


The reason you want to clear the pointer to NULL and size to zero is that that way, you do not accidentally try to access the already freed memory, but you can call getline(&line, &size, handle) to read more lines as the call will simply recognize it does not have a buffer, and will allocate a new one.





You can manipulate the dynamic data in any way you wish, if you are careful. For example:



while (1) {
char *line = NULL;
size_t size = 0;
ssize_t len;

len = getline(&line, &size, stdin);
if (len < 1) {
free(line);
break;
}

/* Do something with the contents of the line */

free(line);
}


will work, but it will be quite slow, because the C library will do at least one malloc() call for every line read, and possibly additional realloc() calls, depending on the line length.



The reason getline() is written as it is, is that it allows reusing the same buffer for any number of lines. If you read files sequentially, you can reuse the same buffer. Let's look at a more complex example:



#define _POSIX_C_SOURCE  200809L
#include <stdlib.h>
#include <locale.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <errno.h>

int main(int argc, char *argv)
{
unsigned long linenum;
char *line = NULL, *in, *out, *end;
size_t size = 0, n;
ssize_t len;
FILE *src;
int arg;

if (!setlocale(LC_ALL, ""))
fprintf(stderr, "Warning: Your C library does not support your current locale.n");

if (argc < 2) {
fprintf(stderr, "n");
fprintf(stderr, "Usage: %s FILENAME [ FILENAME ... ]n", argv[0]);
fprintf(stderr, "n");
exit(EXIT_FAILURE);
}

for (arg = 1; arg < argc; arg++) {

src = fopen(argv[arg], "r");
if (!src) {
fprintf(stderr, "%s: %s.n", argv[arg], strerror(errno));
free(line);
exit(EXIT_FAILURE);
}

linenum = 0;

while (1) {

len = getline(&line, &size, src);
if (len < 1)
break;

linenum++;

/* First character in the line read: */
in = line;
out = line;

/* Pointer to the end-of-string character on the line: */
end = line + len;

/* Skip all leading whitespace characters. */
while (in < end && isspace((unsigned char)(*in)))
in++;

/* Character copy loop. */
while (in < end)
if (isspace((unsigned char)(*in))) {
/* Replace consecutive whitespace characters with spaces. */
*(out++) = ' ';
do {
in++;
} while (in < end && isspace((unsigned char)(*in)));
} else {
/* Copy all other characters as-is. */
*(out++) = *(in++);
}

/* There may be a single space before out. Backtrack it, if so. */
if (out > line && out[-1] == ' ')
out--;

/* Mark the end of the string at out. */
*out = '';

/* Calculate the new length, just for output purposes. */
n = (size_t)(out - line);

/* Print the line. */
printf("%s: Line %lu: '%s' (%zu of %zd characters)n",
argv[arg], linenum, line, n, len);

}
if (!feof(src) || ferror(src)) {
fprintf(stderr, "%s: Read error.n", argv[arg]);
fclose(src);
free(line);
exit(EXIT_FAILURE);
}
if (fclose(src)) {
fprintf(stderr, "%s: Error closing file: %s.n",
argv[arg], strerror(errno));
free(line);
exit(EXIT_FAILURE);
}
}

free(line);
line = NULL;
size = 0;

return EXIT_SUCCESS;
}


If we save the above as say example.c, and compile it using e.g. gcc -Wall -O2 example.c -o example, and run the program supplying it with the names of text files as parameters, for example ./example example.c, it will output something like



example.c: Line 1: '#define _POSIX_C_SOURCE 200809L' (31 of 33 characters)
example.c: Line 2: '#include <stdlib.h>' (19 of 20 characters)
example.c: Line 3: '#include <locale.h>' (19 of 20 characters)
example.c: Line 4: '#include <string.h>' (19 of 20 characters)
example.c: Line 5: '#include <stdio.h>' (18 of 19 characters)
example.c: Line 6: '#include <ctype.h>' (18 of 19 characters)
example.c: Line 7: '#include <errno.h>' (18 of 19 characters)
example.c: Line 8: '' (0 of 1 characters)
example.c: Line 9: 'int main(int argc, char *argv)' (32 of 33 characters)


What the program does, is simply read each specified file line by line, remove any leading and trailing whitespace on each line, and combine all consecutive whitespace into a single space. The smaller character count is the number of characters left (and shown), the larger number is the original number of chars read from the file.



Additional notes on the example program, if it happens to interest you




  • The setlocale(LC_ALL, "") call tells your C library to use the users locale (usually defined in the LANG or LC_ALL environment variables). This program uses only the character type definitions for the character set used by the current locale (to determine which codes are "whitespace"), so this could also be limited to that, via setlocale(LC_CTYPE, ""). The call will return NULL if the current locale is not supported by the C library. Usually that is because of an error in the user configuration, so it is useful to have the program warn then.


  • The isspace() (and all other is*() functions defined in <ctype.h>) take an unsigned character code (or EOF). Because char type can be signed or unsigned, we explicitly cast the character to (unsigned char) before supplying to the function. Consider this silly historical baggage that we just have to deal with this way.


  • Because line points to the beginning of the dynamically allocated memory buffer, we must not modify it (except via realloc(), or free() and then set to NULL). If we do modify it, any subsequent getline() or free() call using that pointer will likely freak out, and crash the program, since they really need the pointer to point to the beginning of the buffer, not just somewhere inside it.



  • I like using pointers (char *in, *out, *end) instead of indexes. Here, in starts at line, and goes up to but not including line+len, which is where getline() put the end-of-string nul to indicate the end of the line. That's why I also often use a pointer named end to point to that. The out starts at line also, but only increases when characters are kept in a line.



    If you think about a row of lettered tiles, like in scrabble, out points to the next position you'll put a kept tile, and in points to the next tile you get.



  • When getline() or getdelim() returns a zero or a negative value (or fgets() returns NULL), it means that either there was no more data to read, or the operation failed for some other reason.



  • After the loop, (!feof(src) || ferror(src)) checks if the input stream was read completely without errors. Well, rather, the inverse: the expression is true only if an error occurred, or the entire file was not read.



    If I had written data to some file, say FILE *dst, I typically precede this test with if (fflush(dst)) test. It is true if there is an error writing the last of the data buffered by the C library to the file.




  • The fclose(src) closes the file. I personally prefer to verify its return value, because even though currently it can only fail in very specific circumstances, I as an user would definitely prefer to know if the OS had issues writing my data! The test costs basically nothing, but may be crucial for the user. I do not want any programs to "forget" telling me there was a problem, when working on my data; my data is important to me.





    • free(NULL) is safe, and does nothing. (Also, realloc(NULL, size) is equivalent to malloc(size), so if you initialize a pointer to NULL, you don't need an initial malloc, you can just realloc() it always to the size you need.)




I suggest you play with the above code. You can even run it under ltrace (ltrace ./example example.c) to see which standard C library calls are actually performed, and their results; or under strace (strace ./example example.c) to see the syscalls (from the process to the OS kernel proper).



As an example, you could add say



        if (linenum == 7) {
/* We skip line 7, and even destroy it! Muahhahah! */
free(line);
line = NULL;
size = 0;
continue;
}


just after the linenum++ line, to see what happens to the seventh lines of the text files. (They're skipped, and even if the buffer is released, nothing bad happens (because continue starts the next iteration of the while loop body), as the next getline() will just dynamically allocate a new line.



If you decide you want to keep a copy of part of the line, just calculate the length you need adding one for the end-of-string nul (), allocate that many chars for the duplicate (sizeof (char) == 1 in C, always; so malloc() et al. take the number of chars to allocate for, really), memcpy() the data, and add the terminating nul. For example,



char *sdup(const char *const source, const size_t  length)
{
char *s;

s = malloc(length + 1);
if (!s) {
/* Either return NULL, or: */
fprintf(stderr, "sdup(): Not enough memory for %zu chars.n", length + 1);
exit(EXIT_FAILURE);
}

if (length > 0)
memcpy(s, source, length);

s[length] = '';
return s;
}


If you want the full string (up to end of string nul), you can use the POSIX.1-2008 strdup() instead.






share|improve this answer























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54266432%2fsegmentation-error-with-getline-function%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    4 Answers
    4






    active

    oldest

    votes








    4 Answers
    4






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    2














    You forgot to initialize buffer. And you'll better end your printf(3) format control string with n or else call fflush(3) before any input (since stdio(3) is buffered).



    An uninitialized pointer contains garbage. Using it is undefined behavior. Be scared !



    So my suggestion is to code



    size_t bufsiz = 64;
    char *buffer = malloc(bufsiz);
    if (!buffer) { perror("malloc buffer"); exit(EXIT_FAILURE); };


    and later



    printf("Salut ! Quel est ton nom ?n");
    characters = getline(&buffer,&bufsize,stdin);


    Next time enable all warnings and debug info when compiling, so compile your code with gcc -Wall -Wextra -g if using GCC. You would have got some warnings.



    Of course, read How to debug small programs and debugging with GDB



    On Linux, in your particular case, you could be interested in using readline(3) instead of getline(3).



    Don't forget to read the documentation of every function that you are using (e.g. here, if it is a standard C one).






    share|improve this answer


























    • Thank you It worked! but if my buffer wasn't poiting any memory , why does it did work with all my program and never had this error ?

      – Chetrit
      Jan 19 at 11:19











    • Follow all the links I am giving in my answer

      – Basile Starynkevitch
      Jan 19 at 11:21











    • Thank you very much ! Have a great day !

      – Chetrit
      Jan 19 at 11:29
















    2














    You forgot to initialize buffer. And you'll better end your printf(3) format control string with n or else call fflush(3) before any input (since stdio(3) is buffered).



    An uninitialized pointer contains garbage. Using it is undefined behavior. Be scared !



    So my suggestion is to code



    size_t bufsiz = 64;
    char *buffer = malloc(bufsiz);
    if (!buffer) { perror("malloc buffer"); exit(EXIT_FAILURE); };


    and later



    printf("Salut ! Quel est ton nom ?n");
    characters = getline(&buffer,&bufsize,stdin);


    Next time enable all warnings and debug info when compiling, so compile your code with gcc -Wall -Wextra -g if using GCC. You would have got some warnings.



    Of course, read How to debug small programs and debugging with GDB



    On Linux, in your particular case, you could be interested in using readline(3) instead of getline(3).



    Don't forget to read the documentation of every function that you are using (e.g. here, if it is a standard C one).






    share|improve this answer


























    • Thank you It worked! but if my buffer wasn't poiting any memory , why does it did work with all my program and never had this error ?

      – Chetrit
      Jan 19 at 11:19











    • Follow all the links I am giving in my answer

      – Basile Starynkevitch
      Jan 19 at 11:21











    • Thank you very much ! Have a great day !

      – Chetrit
      Jan 19 at 11:29














    2












    2








    2







    You forgot to initialize buffer. And you'll better end your printf(3) format control string with n or else call fflush(3) before any input (since stdio(3) is buffered).



    An uninitialized pointer contains garbage. Using it is undefined behavior. Be scared !



    So my suggestion is to code



    size_t bufsiz = 64;
    char *buffer = malloc(bufsiz);
    if (!buffer) { perror("malloc buffer"); exit(EXIT_FAILURE); };


    and later



    printf("Salut ! Quel est ton nom ?n");
    characters = getline(&buffer,&bufsize,stdin);


    Next time enable all warnings and debug info when compiling, so compile your code with gcc -Wall -Wextra -g if using GCC. You would have got some warnings.



    Of course, read How to debug small programs and debugging with GDB



    On Linux, in your particular case, you could be interested in using readline(3) instead of getline(3).



    Don't forget to read the documentation of every function that you are using (e.g. here, if it is a standard C one).






    share|improve this answer















    You forgot to initialize buffer. And you'll better end your printf(3) format control string with n or else call fflush(3) before any input (since stdio(3) is buffered).



    An uninitialized pointer contains garbage. Using it is undefined behavior. Be scared !



    So my suggestion is to code



    size_t bufsiz = 64;
    char *buffer = malloc(bufsiz);
    if (!buffer) { perror("malloc buffer"); exit(EXIT_FAILURE); };


    and later



    printf("Salut ! Quel est ton nom ?n");
    characters = getline(&buffer,&bufsize,stdin);


    Next time enable all warnings and debug info when compiling, so compile your code with gcc -Wall -Wextra -g if using GCC. You would have got some warnings.



    Of course, read How to debug small programs and debugging with GDB



    On Linux, in your particular case, you could be interested in using readline(3) instead of getline(3).



    Don't forget to read the documentation of every function that you are using (e.g. here, if it is a standard C one).







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Jan 19 at 11:32

























    answered Jan 19 at 11:10









    Basile StarynkevitchBasile Starynkevitch

    178k13169364




    178k13169364













    • Thank you It worked! but if my buffer wasn't poiting any memory , why does it did work with all my program and never had this error ?

      – Chetrit
      Jan 19 at 11:19











    • Follow all the links I am giving in my answer

      – Basile Starynkevitch
      Jan 19 at 11:21











    • Thank you very much ! Have a great day !

      – Chetrit
      Jan 19 at 11:29



















    • Thank you It worked! but if my buffer wasn't poiting any memory , why does it did work with all my program and never had this error ?

      – Chetrit
      Jan 19 at 11:19











    • Follow all the links I am giving in my answer

      – Basile Starynkevitch
      Jan 19 at 11:21











    • Thank you very much ! Have a great day !

      – Chetrit
      Jan 19 at 11:29

















    Thank you It worked! but if my buffer wasn't poiting any memory , why does it did work with all my program and never had this error ?

    – Chetrit
    Jan 19 at 11:19





    Thank you It worked! but if my buffer wasn't poiting any memory , why does it did work with all my program and never had this error ?

    – Chetrit
    Jan 19 at 11:19













    Follow all the links I am giving in my answer

    – Basile Starynkevitch
    Jan 19 at 11:21





    Follow all the links I am giving in my answer

    – Basile Starynkevitch
    Jan 19 at 11:21













    Thank you very much ! Have a great day !

    – Chetrit
    Jan 19 at 11:29





    Thank you very much ! Have a great day !

    – Chetrit
    Jan 19 at 11:29













    2














    getline() can be used in two different ways:




    1. Read into a buffer provided by the caller.

    2. Allocate memory when reading.


    To use 1. initialise the pointer passed to point to valid memory and pass as well the size of the latter.



    #define INITIAL_SIZE (42)

    int main(void)
    {
    char * buffer = malloc(INITIAL_SIZE * sizeof *buffer);
    size_t bufsize = INITIAL_SIZE;
    ssize_t characters = getline(&buffer, &bufsize, stdin);
    if (-1 == characters)
    {
    /* handle error. */
    }
    else
    {
    /* use buffer */
    }

    free(buffer); /* Free buffer. */
    }


    To use 2. initialise the pointer passed to NULL and pass 0 as size.



    int main(void)
    {
    char * buffer = NULL;
    size_t bufsize = 0;
    ssize_t characters = getline(&buffer, &bufsize, stdin);
    if (-1 == characters)
    {
    /* handle error. */
    }
    else
    {
    /* use buffer */
    }

    free(buffer); /* Free buffer. */
    }


    Note: getline() returns ssize_t not size_t.






    share|improve this answer


























    • Outsh! @NominalAnimal Fixed! Thx! :}

      – alk
      Jan 19 at 13:32


















    2














    getline() can be used in two different ways:




    1. Read into a buffer provided by the caller.

    2. Allocate memory when reading.


    To use 1. initialise the pointer passed to point to valid memory and pass as well the size of the latter.



    #define INITIAL_SIZE (42)

    int main(void)
    {
    char * buffer = malloc(INITIAL_SIZE * sizeof *buffer);
    size_t bufsize = INITIAL_SIZE;
    ssize_t characters = getline(&buffer, &bufsize, stdin);
    if (-1 == characters)
    {
    /* handle error. */
    }
    else
    {
    /* use buffer */
    }

    free(buffer); /* Free buffer. */
    }


    To use 2. initialise the pointer passed to NULL and pass 0 as size.



    int main(void)
    {
    char * buffer = NULL;
    size_t bufsize = 0;
    ssize_t characters = getline(&buffer, &bufsize, stdin);
    if (-1 == characters)
    {
    /* handle error. */
    }
    else
    {
    /* use buffer */
    }

    free(buffer); /* Free buffer. */
    }


    Note: getline() returns ssize_t not size_t.






    share|improve this answer


























    • Outsh! @NominalAnimal Fixed! Thx! :}

      – alk
      Jan 19 at 13:32
















    2












    2








    2







    getline() can be used in two different ways:




    1. Read into a buffer provided by the caller.

    2. Allocate memory when reading.


    To use 1. initialise the pointer passed to point to valid memory and pass as well the size of the latter.



    #define INITIAL_SIZE (42)

    int main(void)
    {
    char * buffer = malloc(INITIAL_SIZE * sizeof *buffer);
    size_t bufsize = INITIAL_SIZE;
    ssize_t characters = getline(&buffer, &bufsize, stdin);
    if (-1 == characters)
    {
    /* handle error. */
    }
    else
    {
    /* use buffer */
    }

    free(buffer); /* Free buffer. */
    }


    To use 2. initialise the pointer passed to NULL and pass 0 as size.



    int main(void)
    {
    char * buffer = NULL;
    size_t bufsize = 0;
    ssize_t characters = getline(&buffer, &bufsize, stdin);
    if (-1 == characters)
    {
    /* handle error. */
    }
    else
    {
    /* use buffer */
    }

    free(buffer); /* Free buffer. */
    }


    Note: getline() returns ssize_t not size_t.






    share|improve this answer















    getline() can be used in two different ways:




    1. Read into a buffer provided by the caller.

    2. Allocate memory when reading.


    To use 1. initialise the pointer passed to point to valid memory and pass as well the size of the latter.



    #define INITIAL_SIZE (42)

    int main(void)
    {
    char * buffer = malloc(INITIAL_SIZE * sizeof *buffer);
    size_t bufsize = INITIAL_SIZE;
    ssize_t characters = getline(&buffer, &bufsize, stdin);
    if (-1 == characters)
    {
    /* handle error. */
    }
    else
    {
    /* use buffer */
    }

    free(buffer); /* Free buffer. */
    }


    To use 2. initialise the pointer passed to NULL and pass 0 as size.



    int main(void)
    {
    char * buffer = NULL;
    size_t bufsize = 0;
    ssize_t characters = getline(&buffer, &bufsize, stdin);
    if (-1 == characters)
    {
    /* handle error. */
    }
    else
    {
    /* use buffer */
    }

    free(buffer); /* Free buffer. */
    }


    Note: getline() returns ssize_t not size_t.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Jan 19 at 13:35

























    answered Jan 19 at 11:14









    alkalk

    58.6k763172




    58.6k763172













    • Outsh! @NominalAnimal Fixed! Thx! :}

      – alk
      Jan 19 at 13:32





















    • Outsh! @NominalAnimal Fixed! Thx! :}

      – alk
      Jan 19 at 13:32



















    Outsh! @NominalAnimal Fixed! Thx! :}

    – alk
    Jan 19 at 13:32







    Outsh! @NominalAnimal Fixed! Thx! :}

    – alk
    Jan 19 at 13:32













    1














    'buffer' variable is pointing to some garbage memory address. You need to allocate necessary memory first, using 'malloc' function or make 'buffer' a static array, instead of pointer.






    share|improve this answer



















    • 1





      "You need to allocate [...] memory first" not necessarily. Please see my answer of an alternative to use getline().

      – alk
      Jan 19 at 11:21
















    1














    'buffer' variable is pointing to some garbage memory address. You need to allocate necessary memory first, using 'malloc' function or make 'buffer' a static array, instead of pointer.






    share|improve this answer



















    • 1





      "You need to allocate [...] memory first" not necessarily. Please see my answer of an alternative to use getline().

      – alk
      Jan 19 at 11:21














    1












    1








    1







    'buffer' variable is pointing to some garbage memory address. You need to allocate necessary memory first, using 'malloc' function or make 'buffer' a static array, instead of pointer.






    share|improve this answer













    'buffer' variable is pointing to some garbage memory address. You need to allocate necessary memory first, using 'malloc' function or make 'buffer' a static array, instead of pointer.







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Jan 19 at 11:11









    Starl1ghtStarl1ght

    3,35111140




    3,35111140








    • 1





      "You need to allocate [...] memory first" not necessarily. Please see my answer of an alternative to use getline().

      – alk
      Jan 19 at 11:21














    • 1





      "You need to allocate [...] memory first" not necessarily. Please see my answer of an alternative to use getline().

      – alk
      Jan 19 at 11:21








    1




    1





    "You need to allocate [...] memory first" not necessarily. Please see my answer of an alternative to use getline().

    – alk
    Jan 19 at 11:21





    "You need to allocate [...] memory first" not necessarily. Please see my answer of an alternative to use getline().

    – alk
    Jan 19 at 11:21











    0














    getline() is a POSIX.1 function, which reads lines into dynamically allocated buffers, allowing lines of any length (limited only by the amount of available memory). It returns the number of characters read, or -1 if there is no more input, or an error occurred.



    Here is one example use pattern:



        char   *line = NULL;
    size_t size = 0;
    ssize_t len;

    while (1) {

    len = getline(&line, &size, stdin);
    if (len < 1)
    break;

    /* Do something with the input line */

    }


    At any point, you can release the dynamically allocated buffer using



        free(line);
    line = NULL;
    size = 0;


    The reason you want to clear the pointer to NULL and size to zero is that that way, you do not accidentally try to access the already freed memory, but you can call getline(&line, &size, handle) to read more lines as the call will simply recognize it does not have a buffer, and will allocate a new one.





    You can manipulate the dynamic data in any way you wish, if you are careful. For example:



    while (1) {
    char *line = NULL;
    size_t size = 0;
    ssize_t len;

    len = getline(&line, &size, stdin);
    if (len < 1) {
    free(line);
    break;
    }

    /* Do something with the contents of the line */

    free(line);
    }


    will work, but it will be quite slow, because the C library will do at least one malloc() call for every line read, and possibly additional realloc() calls, depending on the line length.



    The reason getline() is written as it is, is that it allows reusing the same buffer for any number of lines. If you read files sequentially, you can reuse the same buffer. Let's look at a more complex example:



    #define _POSIX_C_SOURCE  200809L
    #include <stdlib.h>
    #include <locale.h>
    #include <string.h>
    #include <stdio.h>
    #include <ctype.h>
    #include <errno.h>

    int main(int argc, char *argv)
    {
    unsigned long linenum;
    char *line = NULL, *in, *out, *end;
    size_t size = 0, n;
    ssize_t len;
    FILE *src;
    int arg;

    if (!setlocale(LC_ALL, ""))
    fprintf(stderr, "Warning: Your C library does not support your current locale.n");

    if (argc < 2) {
    fprintf(stderr, "n");
    fprintf(stderr, "Usage: %s FILENAME [ FILENAME ... ]n", argv[0]);
    fprintf(stderr, "n");
    exit(EXIT_FAILURE);
    }

    for (arg = 1; arg < argc; arg++) {

    src = fopen(argv[arg], "r");
    if (!src) {
    fprintf(stderr, "%s: %s.n", argv[arg], strerror(errno));
    free(line);
    exit(EXIT_FAILURE);
    }

    linenum = 0;

    while (1) {

    len = getline(&line, &size, src);
    if (len < 1)
    break;

    linenum++;

    /* First character in the line read: */
    in = line;
    out = line;

    /* Pointer to the end-of-string character on the line: */
    end = line + len;

    /* Skip all leading whitespace characters. */
    while (in < end && isspace((unsigned char)(*in)))
    in++;

    /* Character copy loop. */
    while (in < end)
    if (isspace((unsigned char)(*in))) {
    /* Replace consecutive whitespace characters with spaces. */
    *(out++) = ' ';
    do {
    in++;
    } while (in < end && isspace((unsigned char)(*in)));
    } else {
    /* Copy all other characters as-is. */
    *(out++) = *(in++);
    }

    /* There may be a single space before out. Backtrack it, if so. */
    if (out > line && out[-1] == ' ')
    out--;

    /* Mark the end of the string at out. */
    *out = '';

    /* Calculate the new length, just for output purposes. */
    n = (size_t)(out - line);

    /* Print the line. */
    printf("%s: Line %lu: '%s' (%zu of %zd characters)n",
    argv[arg], linenum, line, n, len);

    }
    if (!feof(src) || ferror(src)) {
    fprintf(stderr, "%s: Read error.n", argv[arg]);
    fclose(src);
    free(line);
    exit(EXIT_FAILURE);
    }
    if (fclose(src)) {
    fprintf(stderr, "%s: Error closing file: %s.n",
    argv[arg], strerror(errno));
    free(line);
    exit(EXIT_FAILURE);
    }
    }

    free(line);
    line = NULL;
    size = 0;

    return EXIT_SUCCESS;
    }


    If we save the above as say example.c, and compile it using e.g. gcc -Wall -O2 example.c -o example, and run the program supplying it with the names of text files as parameters, for example ./example example.c, it will output something like



    example.c: Line 1: '#define _POSIX_C_SOURCE 200809L' (31 of 33 characters)
    example.c: Line 2: '#include <stdlib.h>' (19 of 20 characters)
    example.c: Line 3: '#include <locale.h>' (19 of 20 characters)
    example.c: Line 4: '#include <string.h>' (19 of 20 characters)
    example.c: Line 5: '#include <stdio.h>' (18 of 19 characters)
    example.c: Line 6: '#include <ctype.h>' (18 of 19 characters)
    example.c: Line 7: '#include <errno.h>' (18 of 19 characters)
    example.c: Line 8: '' (0 of 1 characters)
    example.c: Line 9: 'int main(int argc, char *argv)' (32 of 33 characters)


    What the program does, is simply read each specified file line by line, remove any leading and trailing whitespace on each line, and combine all consecutive whitespace into a single space. The smaller character count is the number of characters left (and shown), the larger number is the original number of chars read from the file.



    Additional notes on the example program, if it happens to interest you




    • The setlocale(LC_ALL, "") call tells your C library to use the users locale (usually defined in the LANG or LC_ALL environment variables). This program uses only the character type definitions for the character set used by the current locale (to determine which codes are "whitespace"), so this could also be limited to that, via setlocale(LC_CTYPE, ""). The call will return NULL if the current locale is not supported by the C library. Usually that is because of an error in the user configuration, so it is useful to have the program warn then.


    • The isspace() (and all other is*() functions defined in <ctype.h>) take an unsigned character code (or EOF). Because char type can be signed or unsigned, we explicitly cast the character to (unsigned char) before supplying to the function. Consider this silly historical baggage that we just have to deal with this way.


    • Because line points to the beginning of the dynamically allocated memory buffer, we must not modify it (except via realloc(), or free() and then set to NULL). If we do modify it, any subsequent getline() or free() call using that pointer will likely freak out, and crash the program, since they really need the pointer to point to the beginning of the buffer, not just somewhere inside it.



    • I like using pointers (char *in, *out, *end) instead of indexes. Here, in starts at line, and goes up to but not including line+len, which is where getline() put the end-of-string nul to indicate the end of the line. That's why I also often use a pointer named end to point to that. The out starts at line also, but only increases when characters are kept in a line.



      If you think about a row of lettered tiles, like in scrabble, out points to the next position you'll put a kept tile, and in points to the next tile you get.



    • When getline() or getdelim() returns a zero or a negative value (or fgets() returns NULL), it means that either there was no more data to read, or the operation failed for some other reason.



    • After the loop, (!feof(src) || ferror(src)) checks if the input stream was read completely without errors. Well, rather, the inverse: the expression is true only if an error occurred, or the entire file was not read.



      If I had written data to some file, say FILE *dst, I typically precede this test with if (fflush(dst)) test. It is true if there is an error writing the last of the data buffered by the C library to the file.




    • The fclose(src) closes the file. I personally prefer to verify its return value, because even though currently it can only fail in very specific circumstances, I as an user would definitely prefer to know if the OS had issues writing my data! The test costs basically nothing, but may be crucial for the user. I do not want any programs to "forget" telling me there was a problem, when working on my data; my data is important to me.





      • free(NULL) is safe, and does nothing. (Also, realloc(NULL, size) is equivalent to malloc(size), so if you initialize a pointer to NULL, you don't need an initial malloc, you can just realloc() it always to the size you need.)




    I suggest you play with the above code. You can even run it under ltrace (ltrace ./example example.c) to see which standard C library calls are actually performed, and their results; or under strace (strace ./example example.c) to see the syscalls (from the process to the OS kernel proper).



    As an example, you could add say



            if (linenum == 7) {
    /* We skip line 7, and even destroy it! Muahhahah! */
    free(line);
    line = NULL;
    size = 0;
    continue;
    }


    just after the linenum++ line, to see what happens to the seventh lines of the text files. (They're skipped, and even if the buffer is released, nothing bad happens (because continue starts the next iteration of the while loop body), as the next getline() will just dynamically allocate a new line.



    If you decide you want to keep a copy of part of the line, just calculate the length you need adding one for the end-of-string nul (), allocate that many chars for the duplicate (sizeof (char) == 1 in C, always; so malloc() et al. take the number of chars to allocate for, really), memcpy() the data, and add the terminating nul. For example,



    char *sdup(const char *const source, const size_t  length)
    {
    char *s;

    s = malloc(length + 1);
    if (!s) {
    /* Either return NULL, or: */
    fprintf(stderr, "sdup(): Not enough memory for %zu chars.n", length + 1);
    exit(EXIT_FAILURE);
    }

    if (length > 0)
    memcpy(s, source, length);

    s[length] = '';
    return s;
    }


    If you want the full string (up to end of string nul), you can use the POSIX.1-2008 strdup() instead.






    share|improve this answer




























      0














      getline() is a POSIX.1 function, which reads lines into dynamically allocated buffers, allowing lines of any length (limited only by the amount of available memory). It returns the number of characters read, or -1 if there is no more input, or an error occurred.



      Here is one example use pattern:



          char   *line = NULL;
      size_t size = 0;
      ssize_t len;

      while (1) {

      len = getline(&line, &size, stdin);
      if (len < 1)
      break;

      /* Do something with the input line */

      }


      At any point, you can release the dynamically allocated buffer using



          free(line);
      line = NULL;
      size = 0;


      The reason you want to clear the pointer to NULL and size to zero is that that way, you do not accidentally try to access the already freed memory, but you can call getline(&line, &size, handle) to read more lines as the call will simply recognize it does not have a buffer, and will allocate a new one.





      You can manipulate the dynamic data in any way you wish, if you are careful. For example:



      while (1) {
      char *line = NULL;
      size_t size = 0;
      ssize_t len;

      len = getline(&line, &size, stdin);
      if (len < 1) {
      free(line);
      break;
      }

      /* Do something with the contents of the line */

      free(line);
      }


      will work, but it will be quite slow, because the C library will do at least one malloc() call for every line read, and possibly additional realloc() calls, depending on the line length.



      The reason getline() is written as it is, is that it allows reusing the same buffer for any number of lines. If you read files sequentially, you can reuse the same buffer. Let's look at a more complex example:



      #define _POSIX_C_SOURCE  200809L
      #include <stdlib.h>
      #include <locale.h>
      #include <string.h>
      #include <stdio.h>
      #include <ctype.h>
      #include <errno.h>

      int main(int argc, char *argv)
      {
      unsigned long linenum;
      char *line = NULL, *in, *out, *end;
      size_t size = 0, n;
      ssize_t len;
      FILE *src;
      int arg;

      if (!setlocale(LC_ALL, ""))
      fprintf(stderr, "Warning: Your C library does not support your current locale.n");

      if (argc < 2) {
      fprintf(stderr, "n");
      fprintf(stderr, "Usage: %s FILENAME [ FILENAME ... ]n", argv[0]);
      fprintf(stderr, "n");
      exit(EXIT_FAILURE);
      }

      for (arg = 1; arg < argc; arg++) {

      src = fopen(argv[arg], "r");
      if (!src) {
      fprintf(stderr, "%s: %s.n", argv[arg], strerror(errno));
      free(line);
      exit(EXIT_FAILURE);
      }

      linenum = 0;

      while (1) {

      len = getline(&line, &size, src);
      if (len < 1)
      break;

      linenum++;

      /* First character in the line read: */
      in = line;
      out = line;

      /* Pointer to the end-of-string character on the line: */
      end = line + len;

      /* Skip all leading whitespace characters. */
      while (in < end && isspace((unsigned char)(*in)))
      in++;

      /* Character copy loop. */
      while (in < end)
      if (isspace((unsigned char)(*in))) {
      /* Replace consecutive whitespace characters with spaces. */
      *(out++) = ' ';
      do {
      in++;
      } while (in < end && isspace((unsigned char)(*in)));
      } else {
      /* Copy all other characters as-is. */
      *(out++) = *(in++);
      }

      /* There may be a single space before out. Backtrack it, if so. */
      if (out > line && out[-1] == ' ')
      out--;

      /* Mark the end of the string at out. */
      *out = '';

      /* Calculate the new length, just for output purposes. */
      n = (size_t)(out - line);

      /* Print the line. */
      printf("%s: Line %lu: '%s' (%zu of %zd characters)n",
      argv[arg], linenum, line, n, len);

      }
      if (!feof(src) || ferror(src)) {
      fprintf(stderr, "%s: Read error.n", argv[arg]);
      fclose(src);
      free(line);
      exit(EXIT_FAILURE);
      }
      if (fclose(src)) {
      fprintf(stderr, "%s: Error closing file: %s.n",
      argv[arg], strerror(errno));
      free(line);
      exit(EXIT_FAILURE);
      }
      }

      free(line);
      line = NULL;
      size = 0;

      return EXIT_SUCCESS;
      }


      If we save the above as say example.c, and compile it using e.g. gcc -Wall -O2 example.c -o example, and run the program supplying it with the names of text files as parameters, for example ./example example.c, it will output something like



      example.c: Line 1: '#define _POSIX_C_SOURCE 200809L' (31 of 33 characters)
      example.c: Line 2: '#include <stdlib.h>' (19 of 20 characters)
      example.c: Line 3: '#include <locale.h>' (19 of 20 characters)
      example.c: Line 4: '#include <string.h>' (19 of 20 characters)
      example.c: Line 5: '#include <stdio.h>' (18 of 19 characters)
      example.c: Line 6: '#include <ctype.h>' (18 of 19 characters)
      example.c: Line 7: '#include <errno.h>' (18 of 19 characters)
      example.c: Line 8: '' (0 of 1 characters)
      example.c: Line 9: 'int main(int argc, char *argv)' (32 of 33 characters)


      What the program does, is simply read each specified file line by line, remove any leading and trailing whitespace on each line, and combine all consecutive whitespace into a single space. The smaller character count is the number of characters left (and shown), the larger number is the original number of chars read from the file.



      Additional notes on the example program, if it happens to interest you




      • The setlocale(LC_ALL, "") call tells your C library to use the users locale (usually defined in the LANG or LC_ALL environment variables). This program uses only the character type definitions for the character set used by the current locale (to determine which codes are "whitespace"), so this could also be limited to that, via setlocale(LC_CTYPE, ""). The call will return NULL if the current locale is not supported by the C library. Usually that is because of an error in the user configuration, so it is useful to have the program warn then.


      • The isspace() (and all other is*() functions defined in <ctype.h>) take an unsigned character code (or EOF). Because char type can be signed or unsigned, we explicitly cast the character to (unsigned char) before supplying to the function. Consider this silly historical baggage that we just have to deal with this way.


      • Because line points to the beginning of the dynamically allocated memory buffer, we must not modify it (except via realloc(), or free() and then set to NULL). If we do modify it, any subsequent getline() or free() call using that pointer will likely freak out, and crash the program, since they really need the pointer to point to the beginning of the buffer, not just somewhere inside it.



      • I like using pointers (char *in, *out, *end) instead of indexes. Here, in starts at line, and goes up to but not including line+len, which is where getline() put the end-of-string nul to indicate the end of the line. That's why I also often use a pointer named end to point to that. The out starts at line also, but only increases when characters are kept in a line.



        If you think about a row of lettered tiles, like in scrabble, out points to the next position you'll put a kept tile, and in points to the next tile you get.



      • When getline() or getdelim() returns a zero or a negative value (or fgets() returns NULL), it means that either there was no more data to read, or the operation failed for some other reason.



      • After the loop, (!feof(src) || ferror(src)) checks if the input stream was read completely without errors. Well, rather, the inverse: the expression is true only if an error occurred, or the entire file was not read.



        If I had written data to some file, say FILE *dst, I typically precede this test with if (fflush(dst)) test. It is true if there is an error writing the last of the data buffered by the C library to the file.




      • The fclose(src) closes the file. I personally prefer to verify its return value, because even though currently it can only fail in very specific circumstances, I as an user would definitely prefer to know if the OS had issues writing my data! The test costs basically nothing, but may be crucial for the user. I do not want any programs to "forget" telling me there was a problem, when working on my data; my data is important to me.





        • free(NULL) is safe, and does nothing. (Also, realloc(NULL, size) is equivalent to malloc(size), so if you initialize a pointer to NULL, you don't need an initial malloc, you can just realloc() it always to the size you need.)




      I suggest you play with the above code. You can even run it under ltrace (ltrace ./example example.c) to see which standard C library calls are actually performed, and their results; or under strace (strace ./example example.c) to see the syscalls (from the process to the OS kernel proper).



      As an example, you could add say



              if (linenum == 7) {
      /* We skip line 7, and even destroy it! Muahhahah! */
      free(line);
      line = NULL;
      size = 0;
      continue;
      }


      just after the linenum++ line, to see what happens to the seventh lines of the text files. (They're skipped, and even if the buffer is released, nothing bad happens (because continue starts the next iteration of the while loop body), as the next getline() will just dynamically allocate a new line.



      If you decide you want to keep a copy of part of the line, just calculate the length you need adding one for the end-of-string nul (), allocate that many chars for the duplicate (sizeof (char) == 1 in C, always; so malloc() et al. take the number of chars to allocate for, really), memcpy() the data, and add the terminating nul. For example,



      char *sdup(const char *const source, const size_t  length)
      {
      char *s;

      s = malloc(length + 1);
      if (!s) {
      /* Either return NULL, or: */
      fprintf(stderr, "sdup(): Not enough memory for %zu chars.n", length + 1);
      exit(EXIT_FAILURE);
      }

      if (length > 0)
      memcpy(s, source, length);

      s[length] = '';
      return s;
      }


      If you want the full string (up to end of string nul), you can use the POSIX.1-2008 strdup() instead.






      share|improve this answer


























        0












        0








        0







        getline() is a POSIX.1 function, which reads lines into dynamically allocated buffers, allowing lines of any length (limited only by the amount of available memory). It returns the number of characters read, or -1 if there is no more input, or an error occurred.



        Here is one example use pattern:



            char   *line = NULL;
        size_t size = 0;
        ssize_t len;

        while (1) {

        len = getline(&line, &size, stdin);
        if (len < 1)
        break;

        /* Do something with the input line */

        }


        At any point, you can release the dynamically allocated buffer using



            free(line);
        line = NULL;
        size = 0;


        The reason you want to clear the pointer to NULL and size to zero is that that way, you do not accidentally try to access the already freed memory, but you can call getline(&line, &size, handle) to read more lines as the call will simply recognize it does not have a buffer, and will allocate a new one.





        You can manipulate the dynamic data in any way you wish, if you are careful. For example:



        while (1) {
        char *line = NULL;
        size_t size = 0;
        ssize_t len;

        len = getline(&line, &size, stdin);
        if (len < 1) {
        free(line);
        break;
        }

        /* Do something with the contents of the line */

        free(line);
        }


        will work, but it will be quite slow, because the C library will do at least one malloc() call for every line read, and possibly additional realloc() calls, depending on the line length.



        The reason getline() is written as it is, is that it allows reusing the same buffer for any number of lines. If you read files sequentially, you can reuse the same buffer. Let's look at a more complex example:



        #define _POSIX_C_SOURCE  200809L
        #include <stdlib.h>
        #include <locale.h>
        #include <string.h>
        #include <stdio.h>
        #include <ctype.h>
        #include <errno.h>

        int main(int argc, char *argv)
        {
        unsigned long linenum;
        char *line = NULL, *in, *out, *end;
        size_t size = 0, n;
        ssize_t len;
        FILE *src;
        int arg;

        if (!setlocale(LC_ALL, ""))
        fprintf(stderr, "Warning: Your C library does not support your current locale.n");

        if (argc < 2) {
        fprintf(stderr, "n");
        fprintf(stderr, "Usage: %s FILENAME [ FILENAME ... ]n", argv[0]);
        fprintf(stderr, "n");
        exit(EXIT_FAILURE);
        }

        for (arg = 1; arg < argc; arg++) {

        src = fopen(argv[arg], "r");
        if (!src) {
        fprintf(stderr, "%s: %s.n", argv[arg], strerror(errno));
        free(line);
        exit(EXIT_FAILURE);
        }

        linenum = 0;

        while (1) {

        len = getline(&line, &size, src);
        if (len < 1)
        break;

        linenum++;

        /* First character in the line read: */
        in = line;
        out = line;

        /* Pointer to the end-of-string character on the line: */
        end = line + len;

        /* Skip all leading whitespace characters. */
        while (in < end && isspace((unsigned char)(*in)))
        in++;

        /* Character copy loop. */
        while (in < end)
        if (isspace((unsigned char)(*in))) {
        /* Replace consecutive whitespace characters with spaces. */
        *(out++) = ' ';
        do {
        in++;
        } while (in < end && isspace((unsigned char)(*in)));
        } else {
        /* Copy all other characters as-is. */
        *(out++) = *(in++);
        }

        /* There may be a single space before out. Backtrack it, if so. */
        if (out > line && out[-1] == ' ')
        out--;

        /* Mark the end of the string at out. */
        *out = '';

        /* Calculate the new length, just for output purposes. */
        n = (size_t)(out - line);

        /* Print the line. */
        printf("%s: Line %lu: '%s' (%zu of %zd characters)n",
        argv[arg], linenum, line, n, len);

        }
        if (!feof(src) || ferror(src)) {
        fprintf(stderr, "%s: Read error.n", argv[arg]);
        fclose(src);
        free(line);
        exit(EXIT_FAILURE);
        }
        if (fclose(src)) {
        fprintf(stderr, "%s: Error closing file: %s.n",
        argv[arg], strerror(errno));
        free(line);
        exit(EXIT_FAILURE);
        }
        }

        free(line);
        line = NULL;
        size = 0;

        return EXIT_SUCCESS;
        }


        If we save the above as say example.c, and compile it using e.g. gcc -Wall -O2 example.c -o example, and run the program supplying it with the names of text files as parameters, for example ./example example.c, it will output something like



        example.c: Line 1: '#define _POSIX_C_SOURCE 200809L' (31 of 33 characters)
        example.c: Line 2: '#include <stdlib.h>' (19 of 20 characters)
        example.c: Line 3: '#include <locale.h>' (19 of 20 characters)
        example.c: Line 4: '#include <string.h>' (19 of 20 characters)
        example.c: Line 5: '#include <stdio.h>' (18 of 19 characters)
        example.c: Line 6: '#include <ctype.h>' (18 of 19 characters)
        example.c: Line 7: '#include <errno.h>' (18 of 19 characters)
        example.c: Line 8: '' (0 of 1 characters)
        example.c: Line 9: 'int main(int argc, char *argv)' (32 of 33 characters)


        What the program does, is simply read each specified file line by line, remove any leading and trailing whitespace on each line, and combine all consecutive whitespace into a single space. The smaller character count is the number of characters left (and shown), the larger number is the original number of chars read from the file.



        Additional notes on the example program, if it happens to interest you




        • The setlocale(LC_ALL, "") call tells your C library to use the users locale (usually defined in the LANG or LC_ALL environment variables). This program uses only the character type definitions for the character set used by the current locale (to determine which codes are "whitespace"), so this could also be limited to that, via setlocale(LC_CTYPE, ""). The call will return NULL if the current locale is not supported by the C library. Usually that is because of an error in the user configuration, so it is useful to have the program warn then.


        • The isspace() (and all other is*() functions defined in <ctype.h>) take an unsigned character code (or EOF). Because char type can be signed or unsigned, we explicitly cast the character to (unsigned char) before supplying to the function. Consider this silly historical baggage that we just have to deal with this way.


        • Because line points to the beginning of the dynamically allocated memory buffer, we must not modify it (except via realloc(), or free() and then set to NULL). If we do modify it, any subsequent getline() or free() call using that pointer will likely freak out, and crash the program, since they really need the pointer to point to the beginning of the buffer, not just somewhere inside it.



        • I like using pointers (char *in, *out, *end) instead of indexes. Here, in starts at line, and goes up to but not including line+len, which is where getline() put the end-of-string nul to indicate the end of the line. That's why I also often use a pointer named end to point to that. The out starts at line also, but only increases when characters are kept in a line.



          If you think about a row of lettered tiles, like in scrabble, out points to the next position you'll put a kept tile, and in points to the next tile you get.



        • When getline() or getdelim() returns a zero or a negative value (or fgets() returns NULL), it means that either there was no more data to read, or the operation failed for some other reason.



        • After the loop, (!feof(src) || ferror(src)) checks if the input stream was read completely without errors. Well, rather, the inverse: the expression is true only if an error occurred, or the entire file was not read.



          If I had written data to some file, say FILE *dst, I typically precede this test with if (fflush(dst)) test. It is true if there is an error writing the last of the data buffered by the C library to the file.




        • The fclose(src) closes the file. I personally prefer to verify its return value, because even though currently it can only fail in very specific circumstances, I as an user would definitely prefer to know if the OS had issues writing my data! The test costs basically nothing, but may be crucial for the user. I do not want any programs to "forget" telling me there was a problem, when working on my data; my data is important to me.





          • free(NULL) is safe, and does nothing. (Also, realloc(NULL, size) is equivalent to malloc(size), so if you initialize a pointer to NULL, you don't need an initial malloc, you can just realloc() it always to the size you need.)




        I suggest you play with the above code. You can even run it under ltrace (ltrace ./example example.c) to see which standard C library calls are actually performed, and their results; or under strace (strace ./example example.c) to see the syscalls (from the process to the OS kernel proper).



        As an example, you could add say



                if (linenum == 7) {
        /* We skip line 7, and even destroy it! Muahhahah! */
        free(line);
        line = NULL;
        size = 0;
        continue;
        }


        just after the linenum++ line, to see what happens to the seventh lines of the text files. (They're skipped, and even if the buffer is released, nothing bad happens (because continue starts the next iteration of the while loop body), as the next getline() will just dynamically allocate a new line.



        If you decide you want to keep a copy of part of the line, just calculate the length you need adding one for the end-of-string nul (), allocate that many chars for the duplicate (sizeof (char) == 1 in C, always; so malloc() et al. take the number of chars to allocate for, really), memcpy() the data, and add the terminating nul. For example,



        char *sdup(const char *const source, const size_t  length)
        {
        char *s;

        s = malloc(length + 1);
        if (!s) {
        /* Either return NULL, or: */
        fprintf(stderr, "sdup(): Not enough memory for %zu chars.n", length + 1);
        exit(EXIT_FAILURE);
        }

        if (length > 0)
        memcpy(s, source, length);

        s[length] = '';
        return s;
        }


        If you want the full string (up to end of string nul), you can use the POSIX.1-2008 strdup() instead.






        share|improve this answer













        getline() is a POSIX.1 function, which reads lines into dynamically allocated buffers, allowing lines of any length (limited only by the amount of available memory). It returns the number of characters read, or -1 if there is no more input, or an error occurred.



        Here is one example use pattern:



            char   *line = NULL;
        size_t size = 0;
        ssize_t len;

        while (1) {

        len = getline(&line, &size, stdin);
        if (len < 1)
        break;

        /* Do something with the input line */

        }


        At any point, you can release the dynamically allocated buffer using



            free(line);
        line = NULL;
        size = 0;


        The reason you want to clear the pointer to NULL and size to zero is that that way, you do not accidentally try to access the already freed memory, but you can call getline(&line, &size, handle) to read more lines as the call will simply recognize it does not have a buffer, and will allocate a new one.





        You can manipulate the dynamic data in any way you wish, if you are careful. For example:



        while (1) {
        char *line = NULL;
        size_t size = 0;
        ssize_t len;

        len = getline(&line, &size, stdin);
        if (len < 1) {
        free(line);
        break;
        }

        /* Do something with the contents of the line */

        free(line);
        }


        will work, but it will be quite slow, because the C library will do at least one malloc() call for every line read, and possibly additional realloc() calls, depending on the line length.



        The reason getline() is written as it is, is that it allows reusing the same buffer for any number of lines. If you read files sequentially, you can reuse the same buffer. Let's look at a more complex example:



        #define _POSIX_C_SOURCE  200809L
        #include <stdlib.h>
        #include <locale.h>
        #include <string.h>
        #include <stdio.h>
        #include <ctype.h>
        #include <errno.h>

        int main(int argc, char *argv)
        {
        unsigned long linenum;
        char *line = NULL, *in, *out, *end;
        size_t size = 0, n;
        ssize_t len;
        FILE *src;
        int arg;

        if (!setlocale(LC_ALL, ""))
        fprintf(stderr, "Warning: Your C library does not support your current locale.n");

        if (argc < 2) {
        fprintf(stderr, "n");
        fprintf(stderr, "Usage: %s FILENAME [ FILENAME ... ]n", argv[0]);
        fprintf(stderr, "n");
        exit(EXIT_FAILURE);
        }

        for (arg = 1; arg < argc; arg++) {

        src = fopen(argv[arg], "r");
        if (!src) {
        fprintf(stderr, "%s: %s.n", argv[arg], strerror(errno));
        free(line);
        exit(EXIT_FAILURE);
        }

        linenum = 0;

        while (1) {

        len = getline(&line, &size, src);
        if (len < 1)
        break;

        linenum++;

        /* First character in the line read: */
        in = line;
        out = line;

        /* Pointer to the end-of-string character on the line: */
        end = line + len;

        /* Skip all leading whitespace characters. */
        while (in < end && isspace((unsigned char)(*in)))
        in++;

        /* Character copy loop. */
        while (in < end)
        if (isspace((unsigned char)(*in))) {
        /* Replace consecutive whitespace characters with spaces. */
        *(out++) = ' ';
        do {
        in++;
        } while (in < end && isspace((unsigned char)(*in)));
        } else {
        /* Copy all other characters as-is. */
        *(out++) = *(in++);
        }

        /* There may be a single space before out. Backtrack it, if so. */
        if (out > line && out[-1] == ' ')
        out--;

        /* Mark the end of the string at out. */
        *out = '';

        /* Calculate the new length, just for output purposes. */
        n = (size_t)(out - line);

        /* Print the line. */
        printf("%s: Line %lu: '%s' (%zu of %zd characters)n",
        argv[arg], linenum, line, n, len);

        }
        if (!feof(src) || ferror(src)) {
        fprintf(stderr, "%s: Read error.n", argv[arg]);
        fclose(src);
        free(line);
        exit(EXIT_FAILURE);
        }
        if (fclose(src)) {
        fprintf(stderr, "%s: Error closing file: %s.n",
        argv[arg], strerror(errno));
        free(line);
        exit(EXIT_FAILURE);
        }
        }

        free(line);
        line = NULL;
        size = 0;

        return EXIT_SUCCESS;
        }


        If we save the above as say example.c, and compile it using e.g. gcc -Wall -O2 example.c -o example, and run the program supplying it with the names of text files as parameters, for example ./example example.c, it will output something like



        example.c: Line 1: '#define _POSIX_C_SOURCE 200809L' (31 of 33 characters)
        example.c: Line 2: '#include <stdlib.h>' (19 of 20 characters)
        example.c: Line 3: '#include <locale.h>' (19 of 20 characters)
        example.c: Line 4: '#include <string.h>' (19 of 20 characters)
        example.c: Line 5: '#include <stdio.h>' (18 of 19 characters)
        example.c: Line 6: '#include <ctype.h>' (18 of 19 characters)
        example.c: Line 7: '#include <errno.h>' (18 of 19 characters)
        example.c: Line 8: '' (0 of 1 characters)
        example.c: Line 9: 'int main(int argc, char *argv)' (32 of 33 characters)


        What the program does, is simply read each specified file line by line, remove any leading and trailing whitespace on each line, and combine all consecutive whitespace into a single space. The smaller character count is the number of characters left (and shown), the larger number is the original number of chars read from the file.



        Additional notes on the example program, if it happens to interest you




        • The setlocale(LC_ALL, "") call tells your C library to use the users locale (usually defined in the LANG or LC_ALL environment variables). This program uses only the character type definitions for the character set used by the current locale (to determine which codes are "whitespace"), so this could also be limited to that, via setlocale(LC_CTYPE, ""). The call will return NULL if the current locale is not supported by the C library. Usually that is because of an error in the user configuration, so it is useful to have the program warn then.


        • The isspace() (and all other is*() functions defined in <ctype.h>) take an unsigned character code (or EOF). Because char type can be signed or unsigned, we explicitly cast the character to (unsigned char) before supplying to the function. Consider this silly historical baggage that we just have to deal with this way.


        • Because line points to the beginning of the dynamically allocated memory buffer, we must not modify it (except via realloc(), or free() and then set to NULL). If we do modify it, any subsequent getline() or free() call using that pointer will likely freak out, and crash the program, since they really need the pointer to point to the beginning of the buffer, not just somewhere inside it.



        • I like using pointers (char *in, *out, *end) instead of indexes. Here, in starts at line, and goes up to but not including line+len, which is where getline() put the end-of-string nul to indicate the end of the line. That's why I also often use a pointer named end to point to that. The out starts at line also, but only increases when characters are kept in a line.



          If you think about a row of lettered tiles, like in scrabble, out points to the next position you'll put a kept tile, and in points to the next tile you get.



        • When getline() or getdelim() returns a zero or a negative value (or fgets() returns NULL), it means that either there was no more data to read, or the operation failed for some other reason.



        • After the loop, (!feof(src) || ferror(src)) checks if the input stream was read completely without errors. Well, rather, the inverse: the expression is true only if an error occurred, or the entire file was not read.



          If I had written data to some file, say FILE *dst, I typically precede this test with if (fflush(dst)) test. It is true if there is an error writing the last of the data buffered by the C library to the file.




        • The fclose(src) closes the file. I personally prefer to verify its return value, because even though currently it can only fail in very specific circumstances, I as an user would definitely prefer to know if the OS had issues writing my data! The test costs basically nothing, but may be crucial for the user. I do not want any programs to "forget" telling me there was a problem, when working on my data; my data is important to me.





          • free(NULL) is safe, and does nothing. (Also, realloc(NULL, size) is equivalent to malloc(size), so if you initialize a pointer to NULL, you don't need an initial malloc, you can just realloc() it always to the size you need.)




        I suggest you play with the above code. You can even run it under ltrace (ltrace ./example example.c) to see which standard C library calls are actually performed, and their results; or under strace (strace ./example example.c) to see the syscalls (from the process to the OS kernel proper).



        As an example, you could add say



                if (linenum == 7) {
        /* We skip line 7, and even destroy it! Muahhahah! */
        free(line);
        line = NULL;
        size = 0;
        continue;
        }


        just after the linenum++ line, to see what happens to the seventh lines of the text files. (They're skipped, and even if the buffer is released, nothing bad happens (because continue starts the next iteration of the while loop body), as the next getline() will just dynamically allocate a new line.



        If you decide you want to keep a copy of part of the line, just calculate the length you need adding one for the end-of-string nul (), allocate that many chars for the duplicate (sizeof (char) == 1 in C, always; so malloc() et al. take the number of chars to allocate for, really), memcpy() the data, and add the terminating nul. For example,



        char *sdup(const char *const source, const size_t  length)
        {
        char *s;

        s = malloc(length + 1);
        if (!s) {
        /* Either return NULL, or: */
        fprintf(stderr, "sdup(): Not enough memory for %zu chars.n", length + 1);
        exit(EXIT_FAILURE);
        }

        if (length > 0)
        memcpy(s, source, length);

        s[length] = '';
        return s;
        }


        If you want the full string (up to end of string nul), you can use the POSIX.1-2008 strdup() instead.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Jan 19 at 14:14









        Nominal AnimalNominal Animal

        30k33361




        30k33361






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54266432%2fsegmentation-error-with-getline-function%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Liquibase includeAll doesn't find base path

            How to use setInterval in EJS file?

            Petrus Granier-Deferre