aligned_alloc return assignment warning

2020-03-31 04:20发布

问题:

I am cleaning up warnings and found the following error:

warning: assignment makes pointer from integer without a cast buf = aligned_alloc(ALIGN_VALUE,BUF_SZ);

This call is at the very top of the function, essentially:

char* buf;
buf = aligned_alloc(ALIGN_VALUE,BUF_SZ);

It is my understanding that aligned_alloc returns a void *. If cast the return from aligned_alloc to a (char *) I get:

warning: cast to pointer from integer of different size [-Wint-to-pointer-ast] buf = (char*)aligned_alloc(ALIGN_VALUE,BUF_SZ);

The only thing that seems to fix it is

buf = (char*)(uintptr_t)aligned_alloc(ALIGN_VALUE,BUF_SZ);

I have made sure that I am including stdlib.h to avoid implicit declarations referred to in another post. I assumed the cast to char pointer should have resolved this. I am not understanding why the cast to uintptr_t resolves it when void* and uintptr_t are equivalent as far as I understand.

The following is an example of the structure of the file

#include <syslog.h>
#include <linux/fs.h>
#include <linux/hdreg.h>
#include <sys/ioctl.h>
#include <sys/mman.h> // mmap
#include <sys/time.h>
#include <unistd.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <stdio.h>
#include <pthread.h>

void* ax_read_thread(void* arg)
{
    fprintf(stderr, "read thread started\n");
    ax_priv* priv = (ax_priv*)arg;
    char* buf;
    uint32_t count = 0;

    size_t len, transferred = 0;
    buf = (char*)(uintptr_t)aligned_alloc(ALIGN_VALUE,BUF_SZ);

    if (buf == NULL){
        fprintf(stderr, "Aligned alloc failed\n");
        pthread_exit(NULL);
    }
    while(1){
    //do things
    }
}

Thank you for all of the help. I see now that the warning is a result of not indicating the proper version when invoking the compiler.

回答1:

This answer largely summarizes the observations and suggestions from the comments thread, including mine and many others', and wraps them in a bit of expository prose.

In the first place, the problem arises because when you build your program with your present toolchain, in its current form, the aligned_alloc() function is not explicitly declared. In the absence of a declaration, the compiler is inferring its signature: it guesses that the function returns int, and that its parameter types are those obtained via the default argument promotions applied to the types of the actual arguments. The compiler then warns you that those inferences -- especially the return type -- seem inconsistent with how you're actually using the function.

The solution, supposing that the function is available in your C library at all, is to ensure that a correct prototype is provided. You could insert the prototype manually, but you shouldn't. Since it's a standard library function, you should get its declaration from the appropriate header, which for this function is stdlib.h.

HOWEVER, this particular function is new in C11, and evidently you're using a version of GCC that defaults to compiling for an earlier standard. Glibc supports that in part by protecting functions that are new in C11 with a feature-test macro, _ISOC11_SOURCE. This is for your protection: in the event that you're building code written for an earlier standard, and that code happens to provide is own function with the same name as one of C11's new functions, the feature-test system prevents you from suffering a name collision.

If you are indeed writing for C11, as seems to be the case, and if your version of gcc has an option to support C11 (i.e. -std=c11 and/or -std=gnu11), then compiling with that option enabled is your best alternative. If you happen to have a version of Glibc that provides aligned_alloc() but not a version of the compiler that supports a C11 mode, then you have the alternative of manually ensuring that the needed feature test macro is defined to the compiler before any of the standard headers are included. You can do that via a #define at the top of your source file, or via a command-line option to the compiler (e.g. -D_ISOC11_SOURCE=1).

Glibc does have aligned_alloc() from at least version 2.17 (but I think from as early as 2.16). GCC does have a C11 mode since at least version 4.8. If your versions of these components are at least that recent, then it should be sufficient to add the option -std=c11 (to omit GNU extensions) or -std=gnu11 (to support GNU extensions) to your compilation command:

gcc -std=c11 my_program.c