A week ago I made a function called getline in a code that didn't work. Since then, whenever I name a function getline and try to compile it, it doesn't work. If I change the name of the function to something else, it works again. I have restarted my computer (though it really shouldn't require that). How can I get this namespace back?
example error message:
Numens-MBP:c examples mycotic$ cc testing.c
testing.c:9:5: error: conflicting types for 'getline'
int getline(void);
^
/usr/include/stdio.h:448:9: note: previous declaration is here
ssize_t getline(char ** __restrict __linep, size_t * __restrict __lineca...
^
testing.c:13:1: warning: type specifier missing, defaults to 'int'
[-Wimplicit-int]
main()
^
testing.c:20:24: error: too few arguments to function call, expected 3, have 0
while ((len = getline()) > 0)
~~~~~~~ ^
/usr/include/stdio.h:448:1: note: 'getline' declared here
ssize_t getline(char ** __restrict __linep, size_t * __restrict __lineca...
^
testing.c:36:5: error: conflicting types for 'getline'
int getline(void)
^
/usr/include/stdio.h:448:9: note: previous declaration is here
ssize_t getline(char ** __restrict __linep, size_t * __restrict __lineca...
^
1 warning and 3 errors generated.
getline() is a standard C library function. Your function is conflicting with the definition in the standard library.
Pick another name for your function. This one is taken.
The getline() function is a part of POSIX 2008; it was not a part of POSIX 2001 or POSIX 1997. On a Mac, even when you specify -std=c11, the POSIX definitions are enabled by default.
You can work around it by specifying a POSIX version that did not support getline(). Consider this code — but ignore the fact that this 'getline()' outputs a line:
#include <stdio.h>
extern int getline(int);
int getline(int num)
{
printf("%s: %d\n", __func__, num);
return num + 1;
}
int main(void)
{
for (int i = 0; i < 5; i++)
printf("RV = %d\n", getline(i));
return 0;
}
When compiled with GCC 7.1.0, or with either the gcc or clang from XCode 8.3.2, generates all sorts of problems because of the conflicting type of getline() from POSIX and getline() as defined in this code unless you add arguments to prevent the problem. The source was in file gl23.c.
$ /usr/bin/clang -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes \
> -Wstrict-prototypes -Wold-style-definition gl23.c -o gl23
gl23.c:3:12: error: conflicting types for 'getline'
extern int getline(int);
^
/usr/include/stdio.h:448:9: note: previous declaration is here
ssize_t getline(char ** __restrict __linep, size_t * __restrict __linecapp, FILE * __restrict __stream) __OSX_AVAILABLE_STARTIN...
^
gl23.c:5:5: error: conflicting types for 'getline'
int getline(int num)
^
/usr/include/stdio.h:448:9: note: previous declaration is here
ssize_t getline(char ** __restrict __linep, size_t * __restrict __linecapp, FILE * __restrict __stream) __OSX_AVAILABLE_STARTIN...
^
gl23.c:14:38: error: too few arguments to function call, expected 3, have 1
printf("RV = %d\n", getline(i));
~~~~~~~ ^
/usr/include/stdio.h:448:1: note: 'getline' declared here
ssize_t getline(char ** __restrict __linep, size_t * __restrict __linecapp, FILE * __restrict __stream) __OSX_AVAILABLE_STARTIN...
^
3 errors generated.
$
However, if you specify conformance with the old versions of POSIX by adding -D_POSIX_C_SOURCE=200112L or -D_POSIX_C_SOURCE=199506L, then it compiles cleanly, and runs properly, producing:
getline: 0
RV = 1
getline: 1
RV = 2
getline: 2
RV = 3
getline: 3
RV = 4
getline: 4
RV = 5
Be aware that this is only a band-aid solution and it has ramifications — all the other nice new features of POSIX 2008 are no longer accessible.
The only long-term solution is to accept that getline() is now a part of the 'standard' C namespace — the standard is POSIX, of course, not ISO/IEC 9899:2011 — and rename the function. (Yes, it's a nuisance, and K&R 2nd Edition illustrates three versions of getline() that are no longer OK because of this. I had to rename my library function because of this. And the name was not in the reserved namespaces in prior versions of POSIX; there was no way to guess that it would be necessary.)
Related
To start off, I don't get this issue when I compile/"make" the code on a Linux machine which I connect to remotely. I'm experiencing it only on my Windows laptop with Mingw installed -- which I believe is causing the issue.
$ make
gcc -c parser.c
parser.c:34:7: error: conflicting types for 'gets'
34 | char* gets(char *buf, int max)
| ^~~~
In file included from parser.h:4,
from parser.c:1:
c:\mingw\include\stdio.h:709:41: note: previous declaration of 'gets' was here
709 | _CRTIMP __cdecl __MINGW_NOTHROW char * gets (char *);
| ^~~~
Makefile:13: recipe for target 'parser.o' failed
make: *** [parser.o] Error 1
Here's the gets() code as requested:
char* gets(char *buf, int max)
{
int i, cc;
char c;
for(i=0; i+1 < max; ){
cc = read(0, &c, 1);
if(cc < 1) break;
//c = getchar();
buf[i++] = c;
if(c == '\n' || c == '\r')
break;
}
buf[i] = '\0';
return buf;
}
Is there a way to fix this without changing the gets function name? Thank you sm
Your code works on Linux's gcc because the gets function was removed, as it should, since it was deprecated in the C99 standard and removed with C11.
For some reason the Windows MingW distribution still maintains gets and because of that you have a redefinition problem.
So unfortunately you can't use that function name, unless you remove it by hand from stdio.h, as C doesn't allow for function overloading.
Running sample on Linux gcc
Running sample on Windows gcc
As the error says the gets() function is already defined in stdio.h.
One trick you can do is put something like this:
#define gets MY_gets
before your definition of the gets() function.
That way you are actually defining a MY_gets() function which causes no conflict. And when you call gets() later on in your code you are actually calling MY_gets().
If you define gets() in a header file you should include stdio.h first and then put #define gets MY_gets before the declaration of gets() in the header file.
Though I don't see why you want to refine this function if it already exists.
It makes more sense to only define it if needed and surround the function with something like #ifndef HAVE_GETS and endif where HAVE_GETS should be defined based on tests done in the configure/build system.
I'm trying to compile linux kernel 0.0.1 from source code on my 64 bit intel machine.
Only to fill in the boot and main I had to modify all makefiles to get a 32-bit compilation.
So, this is the output of make:
In file included from traps.c:7:0:
../include/string.h:128:22: warning: conflicting types for built-in function ‘strchr’
extern inline char * strchr(const char * s,char c)
^
../include/string.h:145:22: warning: conflicting types for built-in function ‘strrchr’
extern inline char * strrchr(const char * s,char c)
^
../include/string.h:379:22: warning: conflicting types for built-in function ‘memchr’
extern inline void * memchr(const void * cs,char c,int count)
^
../include/string.h:395:22: warning: conflicting types for built-in function ‘memset’
extern inline void * memset(void * s,char c,int count)
^
In file included from traps.c:11:0:
../include/linux/kernel.h:5:1: warning: function return types not compatible due to ‘volatile’
volatile void panic(const char * str);
^
../include/linux/kernel.h:5:1: warning: function return types not compatible due to ‘volatile’
../include/linux/kernel.h:5:1: warning: function return types not compatible due to ‘volatile’
In file included from traps.c:7:0:
../include/string.h: In function ‘strcpy’:
../include/string.h:29:1: error: ‘asm’ operand has impossible constraints
__asm__("cld\n"
^
Makefile:24: set di istruzioni per l'obiettivo "traps.o" non riuscito
The portion of code of string.h is the following:
extern inline char * strcpy(char * dest,const char *src)
{
__asm__("cld\n"
"1:\tlodsb\n\t"
"stosb\n\t"
"testb %%al,%%al\n\t"
"jne 1b"
::"S" (src),"D" (dest):"si","di","ax");
return dest;
}
I don't know why the original code doesn't compile.
Until now I successfully compiled: boot and init subdir.
Many Thanks
I think that the problem is that the register clobber list overlaps with the inputs.
That is, the "S" stands for register esi while "D" stands for register edi; but then the clobber list contains "si" and "di" that are the lower 16 bit pieces of those registers. Maybe old GCC versions ignored that, but newer ones do not allow overlaps.
From the docs here:
Clobber descriptions may not in any way overlap with an input or output operand.
Solution, just remove them from the list:
...
::"S" (src),"D" (dest) :"ax", "cc");
BTW, I also added the clobber to "cc" because that assembly modifies the e flag.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
Good evening,
I am working through the exercises in Kernighan's and Ritchie's classic "The C Programming Language".
In several places the exercises have you creating your own version of a function that duplicates the name of of a function in the standard library. Instead of creating an alternate name for my version, I would really like to tell the compiler that I would rather use my version of the function then the standard library function.
To get specific, if I try to compile a solution to exercise 1-18 which removes trailing blanks and tabs from each line of input I use a function 'getline' to read in the line from stdin. Unfortunately, this generates a compiler error because getline is defined in stdio.h.
I have tried using #undef, but couldn't seem to get that to work.
I have searched for other prior similar questions and found [this one][1]; however, it seems to require hacking the standard library header which I would rather not do.
Thank you for your help in advance.
Here is the code (stripped of my comments for shortness):
#include <stdio.h>
#include <stdlib.h>
#define MAXLINE 1000
static size_t getline(char s[], size_t lim) {
char c;
size_t i = 0;
while (--lim > 0 && (c = (char)getchar()) != (char)EOF && c != '\n')
s[i++] = c;
if (c == '\n')
s[i++] = c;
s[i] = '\0';
return i;
}
int main(void) {
char line[MAXLINE] = "";
size_t len = 0;
while ((len = getline(line, MAXLINE)) > 0)
if (len > MAXLINE)
printf("%s", line);
exit(EXIT_SUCCESS);
}
And, the error I get is:
cc -std=c99 -Wall -g -I. -c -o obj/cleantrailsnblanks.o cleantrailsnblanks.c
cleantrailsnblanks.c:14:15: error: static declaration of 'getline' follows non-static declaration
static size_t getline(char s[], size_t lim) {
^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/include/stdio.h:442:9: note: previous declaration is here
ssize_t getline(char ** __restrict, size_t * __restrict, FILE * __restrict) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
^
cleantrailsnblanks.c:35:40: error: too few arguments to function call, expected 3, have 2
while ((len = getline(line, MAXLINE)) > 0)
~~~~~~~ ^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/include/stdio.h:442:1: note: 'getline' declared here
ssize_t getline(char ** __restrict, size_t * __restrict, FILE * __restrict) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
^
2 errors generated.
make: *** [obj/cleantrailsnblanks.o] Error 1
UPDATE 1
After I dropped 'static' from my definition, the error changes to:
cc -std=c99 -Wall -g -I. -c -o obj/cleantrailsnblanks.o cleantrailsnblanks.c
cleantrailsnblanks.c:14:8: error: conflicting types for 'getline'
size_t getline(char s[], size_t lim) {
^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/include/stdio.h:442:9: note: previous declaration is here
ssize_t getline(char ** __restrict, size_t * __restrict, FILE * __restrict) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
^
cleantrailsnblanks.c:35:40: error: too few arguments to function call, expected 3, have 2
while ((len = getline(line, MAXLINE)) > 0)
~~~~~~~ ^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/include/stdio.h:442:1: note: 'getline' declared here
ssize_t getline(char ** __restrict, size_t * __restrict, FILE * __restrict) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
^
2 errors generated.
make: *** [obj/cleantrailsnblanks.o] Error 1
ANSWER
Refer to this discussion: Why do I get a "conflicting types for getline" error when compiling the longest line example in chapter 1 of K&R2?
The solution is to add these two lines prior to including stdio.h:
#undef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 200112L
#include <stdio.h>
This sets the compiles the code using the POSIX.1-2001 standard as opposed to the POSIX.1-2008 standard in which the GNU getline() extension was added to the standard.
Refer to these two discussions (the second is the most relevant):
Why do I get a "conflicting types for getline" error when compiling the longest line example in chapter 1 of K&R2?
Can an ANSI C-compliant implementation include additional functions in its standard library?
The solution is to add these two lines prior to including stdio.h:
#undef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 200112L
#include <stdio.h>
This sets the compiles the code using the POSIX.1-2001 standard as opposed to the POSIX.1-2008 standard in which the GNU getline() extension was added to the standard.
I think your exercice want to make you learn the dynamic injection and shared library.
Compile your file (without the static) like gcc -shared -o libname.so filename.c
On OS X you will need to set 3 environment variable :
setenv DYLD_LIBRARY_PATH .
setenv DYLD_INSERT_LIBRARIES libname.so
setenv DYLD_FORCE_FLAT_NAMESPACE 1
Some others information : http://www.cprogramming.com/tutorial/shared-libraries-linux-gcc.html
EDIT
Let me show you an exemple by changing the result of id
$> id
uid=501(yourname) gid(staff) groups ...
Create a file getuid.c
int getuid() {
return (0);
}
int geteuid() {
return (0);
}
Compile with gcc -shared -o myuid.so getuid.c
You can write nm myuid.so and see the function inside.
then set your environment variable
setenv DYLD_LIBRARY_PATH .
setenv DYLD_INSERT_LIBRARIES libname.so
setenv DYLD_FORCE_FLAT_NAMESPACE 1
it's could be with export, depends of your shell.
then id result look like :
$> id
uid=0(yourname) gid(staff) groups ...
K&R is a (very) old book now, you need to take that in account. Declare/define getline exactly as the manual says (actually). As you are on OSX, the manual says:
SYNOPSIS
#include <stdio.h>
ssize_t
getline(char ** restrict linep, size_t * restrict linecapp, FILE * restrict stream);
Use that prototype.
You may also change the exercise a little bit and rename the function as mygetline if you really wish to use the original prototype.
It depends on how you're going to use it.
If it's just in one .c file, I'd change your method name to something else, then either change all the calls to your new name or add a #define realName overrideName at the top of your file.
If this is more generic, or for mocking in unit testing, I would take your overridden getline method into its own .c file. Compiler it to a .so then tell your system about your override .so file before any other libraries when starting your app.
#include <stdio.h>
#include <string.h>
int main()
{
char arrDst[5] = {0};
char arrSrc[10] = "123456";
memcpy( arrDst, arrSrc, sizeof( arrSrc ) );
return 0;
}
Here in this program it is clear that there is a memory corruption.
Is there any option in gcc compiler by which I can recognize this problem at compile time?
Note: I used valgrind --leak-check=full, but it doesn't help.
$ gcc -Wall -O1 t.c
In file included from /usr/include/string.h:642:0,
from t.c:3:
In function ‘memcpy’,
inlined from ‘main’ at t.c:13:9:
/usr/include/bits/string3.h:52:3: warning: call to __builtin___memcpy_chk
will always overflow destination buffer [enabled by default]
GCC can recognize some of these. That generally requires turning on optimizations (at least -01) and warnings (-Wall, add -Wextra too).
It may not scale to the large program you are really interested in, but you can find this error with Frama-C:
$ frama-c -cpp-command "gcc -C -E -I`frama-c -print-share-path`/libc/ -nostdinc" mem.c `frama-c -print-share-path`/libc/fc_runtime.c -val
...
[value] computing for function memcpy <- main.
Called from mem.c:13.
.../libc/string.h:54:[value] Function memcpy: precondition got status invalid.
This message means that you are calling memcpy() with arguments that do not satisfy its contract. In this case the pre-condition that fails is the first in the list, about the validity of the destination for writing:
/*# requires \valid(((char*)dest)+(0..n - 1));
# requires \valid_read(((char*)src)+(0..n - 1));
# requires \separated(((char *)dest)+(0..n-1),((char *)src)+(0..n-1));
# assigns ((char*)dest)[0..n - 1] \from ((char*)src)[0..n-1];
# assigns \result \from dest;
# ensures memcmp((char*)dest,(char*)src,n) == 0;
# ensures \result == dest;
#*/
extern void *memcpy(void *restrict dest,
const void *restrict src, size_t n);
I'm writing some C code for an embedded linux system using an open_memstream and I don't understand why I am getting a compile warning: assignment makes pointer from integer without a cast
To make things simple, rather than pasting all my code I reproduced the problem with the small example from here:
#include <stdio.h>
#include <stdlib.h>
int
main (void)
{
FILE *stream;
char *buf;
size_t len;
off_t eob;
stream = open_memstream (&buf, &len);
if (stream == NULL)
/* handle error */ ;
fprintf (stream, "hello my world");
fflush (stream);
printf ("buf=%s, len=%zu\n", buf, len);
eob = ftello(stream);
fseeko (stream, 0, SEEK_SET);
fprintf (stream, "good-bye");
fseeko (stream, eob, SEEK_SET);
fclose (stream);
printf ("buf=%s, len=%zu\n", buf, len);
free (buf);
return 0;
}
The code works, but the compiler complains about the line stream = open_memstream (&buf, &len);
What integer is it talking about? We're passing in a pointer to a size_t as required by the function prototype.
FILE *open_memstream(char **bufp, size_t *sizep);
Is there a problem with this code, or do I need to take a look at my compiler? I want to get rid of this warning the right way.
UPDATE:
Using gcc 4.3.2, glibc 2.9
UPDATE 2:
Tried the following:
powerpc-860-linux-gnu-gcc -std=c99 -Wall -D_XOPEN_SOURCE=700 -c source.c
Result:
source.c: In function 'main':
source.c:12: warning: implicit declaration of function 'open_memstream'
source.c:12: warning: assignment makes pointer from integer without a cast
According to this, it seems that _XOPEN_SOURCE=700 is available since glibc 2.10.
Since I'm using glibc 2.9, what other alternatives do I have (other than upgrading glibc)?
UPDATE 3:
Adding the following got rid of the warning:
extern FILE *open_memstream(char **bufp, size_t *sizep);
Is there anything wrong with this solution?
UPDATE 4:
This worked instead of the extern:
powerpc-860-linux-gnu-gcc -std=c99 -Wall -D_GNU_SOURCE -c ops_cmds.c
So according to the manpage, need to use _GNU_SOURCE if glibc pre-2.10 (in my case) and _XOPEN_SOURCE=700 if 2.10+
Define:
#define _POSIX_C_SOURCE 200809L
or
#define _XOPEN_SOURCE 700
in your source code before including stdio.h. Or with gcc you can define and pass the macro value to the source file with -D option:
gcc -std=c99 -Wall -D_XOPEN_SOURCE=700 -c source.c
open_memstream is a POSIX function and its declaration is not visible in your program without this define.
The compiler is complaining about the return value of open_memstream, not about the arguments you pass in.
Your open_memstream is not declared, i.e. the compiler does not see the prototype. So the compiler (apparently pre-C99) assumes that it returns an int. You are forcing that int into stream pointer, which is what triggers the warning about "making pointer form integer".
Make sure open_memstream is declared before you attempt to use it. The prototype is supposed to reside in stdio.h, but it is only available in POSIX.1-2008. You have to enable it explicitly (see other answers).