2

Today I switched to Win11 and can no longer compile a program i was working on with gcc in wsl without "implicit declaration of function ‘mempcpy’" warnings. Before switching to Win 11 (from Win10) everything worked fine.

I get the same behavior for the following test program as well:

#include <stdio.h>
#include <string.h>

int main() {
    char src[] = "Hello, World!";
    char dest[20];

    char* p = mempcpy(dest, src, strlen(src) + 1);
    printf("%s\n", dest);

    //Do something with pointer p

    return 0;
}

Compiling with "gcc -std=gnu17 -o test main.c" gives the the respective warning.

Compiling with clang gives a similar warning and the note: "include the header <string.h> or explicitly provide a declaration for 'mempcpy'"

I tried/checked the following things:

1.) Header in include library: The string.h header is in the include path and has the definition for mempcpy. I even reinstalled libc6-dev to ensure the header file is fine. If I remove the include for stdio.h I get an additional error so it seems that this header is found successfully. stdio.h and string.h are in the same folder so I assume the compiler should be able to see string.h as well.

2.) Using the correct -std=...: This was not necessary before and does not seem to change anything with the new OS installation. I tried several options but nothing changed the behavior. In string.h there is the line #ifdef __USE_GNU. But I assume this would be set to true if std=gnu17 or something similar is set.

3.) Explicitely adding the declaration above int main(){..} with adding the line void *mempcpy(void *dest, const void *src, size_t n);: This removed the warning but it only masks the issue.

If i ignore the warning my program as well as the test program runs fine, but I use -Werror for compilation of the program I am working on so I can not ignore it in this case (even if I wanted to).

OS: Ubuntu 22.04 (in WSL Win11 (10.0.26100)), Compiler: gcc ((Ubuntu 11.4.0-1ubuntu1~22.04.2) 11.4.0)

I am really unsure what else to check/try.

10
  • 2
    Add #define _GNU_SOURCE before the includes. Commented Oct 14 at 15:33
  • 2
    man 3 mempcpy demonstrates how to #include string.h Commented Oct 14 at 15:38
  • 2
    Alternatively, use memcpy, it's not like you're using the different return pointer. Or just use strcpy, which is actually what you're trying to use, and it's much more efficient to boot since it doesn't parse the source string twice (memcpy + strlen). Commented Oct 14 at 15:46
  • 1
    A compiler running in a WSL container does not rely on the Windows host for anything relevant to this question. For the same compilation command, the observed difference can arise only from a difference between the Linux installations in the two WSL containers, either version or configuration. Commented Oct 14 at 16:44
  • 1
    Are you sure you're compiling with -std=gnu17 in the new environment? Because that should not produce the issue you describe, but if you happened to switch to -std=c17 then that would explain everything. Commented Oct 14 at 16:48

1 Answer 1

5

mempcpy isn't a standard C library function, but a GNU extension. As seen in its man page, the following is required to declare it:

#define _GNU_SOURCE
#include <string.h>

So the fix is to add #define _GNU_SOURCE before any includes.

That said, since you discard the value returned by mempcpy, and since mempcpy only varies from the standard C library function memcpy in the value it returns, you could swap in memcpy for mempcpy. Or better yet, you could use strcpy(dest, src).

Sign up to request clarification or add additional context in comments.

7 Comments

Adding #define _GNU_SOURCE does not work but adding #define __USE_GNU resolves the issue for me. In the program (not the example code giving the same compile error) I use the return value (I will change my question to reflect that more clearly).
When I said you have to use #define _GNU_SOURCE before you include string.h, I meant before it's included by the first time in your compilation unit. I suspect you didn't add it early enough because it works for both of us for the snippet you provided. (Well, I'm guessing it works for you based on how you worded things). You could even do it on the command line (-D_GNU_SOURCE)
Can you make it more clear in your answer that the #define needs to go before any #include lines. Then I can accept your answer.
It needs to be defined before the first #include statement.
This did it. Using '#define _GNU_SOURCE' before the first include statement worked. Placing it after e.g. '#include <stdio.h>' but before '#include<string.h>' in the initial example did not work. I did not know of this behavior and it seems strange to me. Anyway this solved my problem. Thank you.
That's because the internal set of macros like __USE_GNU etc. actually get defined by #include <features.h> which is included by the other headers. Only the first #include <features.h> is effective due to include-guard macros, and in your case, that was included by #include <stdio.h> (or possibly an earlier header) before you defined _GNU_SOURCE. So defining _GNU_SOURCE later was less effective, although it may still have had some effect in some non-standard headers.
The behavior I encountered makes much more sense now. Thank you for the clarifications you made.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.