Mac unable to compile C program with getline() using gcc

l0uismustdie

macrumors regular
Original poster
Nov 30, 2009
109
1
Edinburgh, UK
Hello, I am trying to run a C program using getline() and am receiving the following error message:
Code:
14:42@***:~/Documents/c$ gcc -o 3n1 3n1.c 
Undefined symbols:
  "_getline", referenced from:
      _main in ccMhB6EQ.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
The program is as simple as possible:
Code:
#include <stdio.h>

main()
{
  int x;
  char *line;

  x = getline(line,100,stdin);
}
I used the definition from getline() on this site: https://wiki.cs.columbia.edu:8443/display/res/getline()+missing
placed this in a getline.c file and included the getline.c file in my program and this resulted in a segmentation fault upon execution.

Thanks to anyone who can point me in the right direction.
 

robvas

macrumors 68040
Mar 29, 2009
3,068
523
USA
Hello, I am trying to run a C program using getline() and am receiving the following error message:
Code:
14:42@***:~/Documents/c$ gcc -o 3n1 3n1.c 
Undefined symbols:
  "_getline", referenced from:
      _main in ccMhB6EQ.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
The program is as simple as possible:
Code:
#include <stdio.h>

main()
{
  int x;
  char *line;

  x = getline(line,100,stdin);
}
I used the definition from getline() on this site: https://wiki.cs.columbia.edu:8443/display/res/getline()+missing
placed this in a getline.c file and included the getline.c file in my program and this resulted in a segmentation fault upon execution.

Thanks to anyone who can point me in the right direction.
getline is included in OS X (at least it is in Lion, that page may have been from 'the old days')

From a Terminal type 'man getline'
Code:
NAME
     getdelim, getline -- get a line from a stream

LIBRARY
     Standard C Library (libc, -lc)

SYNOPSIS
     #include <stdio.h>

     ssize_t
     getdelim(char ** restrict linep, size_t * restrict linecapp, int delimiter,
         FILE * restrict stream);

     ssize_t
     getline(char ** restrict linep, size_t * restrict linecapp, FILE * restrict stream);

EXAMPLES
     The following code fragment reads lines from a file and writes them to standard output.  The
     fwrite() function is used in case the line contains embedded NUL characters.

           char *line = NULL;
           size_t linecap = 0;
           ssize_t linelen;
           while ((linelen = getline(&line, &linecap, fp)) > 0)
                   fwrite(line, linelen, 1, stdout);
Per the man page, it looks like your first two arguments to the function are not right.
 
Last edited by a moderator:

l0uismustdie

macrumors regular
Original poster
Nov 30, 2009
109
1
Edinburgh, UK
Hmm...this may be the case. I am running Snow Leopard though.
Code:
15:57@***:~/Documents/c$ man getline
No manual entry for getline
 

Mr. Retrofire

macrumors 603
Mar 2, 2010
5,039
470
www.emiliana.cl/en
Hello, I am trying to run a C program using getline() and am receiving the following error message:
man stdio

tells us, that this function is not available in the Standard C lib (10.6.x). So write your own or use this:
getdelim.c
and
getline.c
from
http://www.opensource.apple.com/source/cvs/cvs-42/cvs/lib/
(contains other interesting parts)

Should work without problems. Most configure scripts of open source programs check the availability of getline, which is the reason, why you see no GCC errors regarding getline in most cases.

:)
 

Sander

macrumors 6502
Apr 24, 2008
480
7
It looks like you have to allocate the buffer for the line yourself. So change your code to

Code:
#include <stdio.h>
#define MAX_LINE 100

int main(void)
{
  int x;
  char line[MAX_LINE];

  x = getline(line, MAX_LINE, stdin);
  return 0;
}
You were getting a segmentation fault because the getline() function you added to your program assumed that the buffer passed to it for it to fill was allocated by you beforehand. Instead, it was trying to poke the characters in no man's land.
 

gnasher729

macrumors P6
Nov 25, 2005
16,974
3,893
Code:
#include <stdio.h>

main()
{
  int x;
  char *line;

  x = getline(line,100,stdin);
}
"line" is an unitialised variable. This isn't going to work. If you are a beginner, you should say so to get help appropriate to your level. If you are not a beginner, what do you think is going to happen when getline stores a line of text where that uninitialised variable points to? A crash is the best thing that can happen.
 

AlecZ

macrumors 65816
Sep 11, 2014
1,173
122
Berkeley, CA
man stdio

tells us, that this function is not available in the Standard C lib (10.6.x). So write your own or use this:
getdelim.c
and
getline.c
from
http://www.opensource.apple.com/source/cvs/cvs-42/cvs/lib/
(contains other interesting parts)

Should work without problems. Most configure scripts of open source programs check the availability of getline, which is the reason, why you see no GCC errors regarding getline in most cases.

:)
This is exactly what made it work for me in Snow Leopard. Many thanks. I wish Snow Leopard could have its libraries updated, though! I mean, there's probably SOME way...
 

robvas

macrumors 68040
Mar 29, 2009
3,068
523
USA
not sure what I was thinking in 2012 but you should have been able to do

Code:
gcc -o 3n1 3n1.c getline.c
and have that work!
 

denniscote

macrumors newbie
Jul 19, 2011
18
1
Please read the man page more carefully

getline is included in OS X (at least it is in Lion, that page may have been from 'the old days')

From a Terminal type 'man getline'
Code:
NAME
     getdelim, getline -- get a line from a stream

LIBRARY
     Standard C Library (libc, -lc)

SYNOPSIS
     #include <stdio.h>

     ssize_t
     getdelim(char ** restrict linep, size_t * restrict linecapp, int delimiter,
         FILE * restrict stream);

     ssize_t
     getline(char ** restrict linep, size_t * restrict linecapp, FILE * restrict stream);

EXAMPLES
     The following code fragment reads lines from a file and writes them to standard output.  The
     fwrite() function is used in case the line contains embedded NUL characters.

           char *line = NULL;
           size_t linecap = 0;
           ssize_t linelen;
           while ((linelen = getline(&line, &linecap, fp)) > 0)
                   fwrite(line, linelen, 1, stdout);
Per the man page, it looks like your first two arguments to the function are not right.
You are correct about the first two arguments being wrong, but some of the later suggestions are also wrong.

Getline() can use a buffer supplied by the caller, or it can allocate a buffer and return it to the caller. If the user supplies a buffer, it must be a malloc'd buffer (not a fixed char array) since it may need to be realloc'd if the line is longer than the supplied buffer. It's probably easier to let getline() allocate the buffer. You indicate this by passing in the address of a NULL pointer.

The docs say that getline() wants a char**, the address of a buffer pointer, and a size_t *, the address of a buffer length variable. It will read the line and update the buffer pointer to point at the new line buffer (which it has allocated) and set the capacity variable to the length of the buffer it has allocated. These are both output variables from getline(), so it needs the address of the caller's variables so it can update them.

Code:
getline(&line, &linecap, fp)
In the example code they pass the address of the local variables line and linecap. Note that the line variable was initialized to NULL before calling getline(). Getline() will allocate a buffer, read the line, and return the length of the line it read (or an error code). Before returning it will update the caller's buffer pointer and buffer length variables.

Once getline() has allocated a buffer, that same buffer can be passed back in to subsequent calls where its contents will be overwritten.

To prevent a memory leak the allocated buffer must be free'd by the caller when it is done with it. This isn't done in the example code, but there should be a free(line) call after the loop ends.

HTH
Dennis Cote
 
Last edited:
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.