aligned_alloc返回分配警告

时间:2017-03-02 23:24:47

标签: c linux memory memory-management

我正在清理警告并发现以下错误:

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

此调用位于函数的最顶层,基本上是:

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

据我所知,aligned_alloc返回void *。如果将对象从aligned_alloc转换为(char *),我得到:

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

似乎唯一能解决的问题是

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

我确保我包含stdlib.h以避免在另一篇文章中提到的隐式声明。我假设cast to char指针应该解决了这个问题。我不明白为什么当void *时,uintptr_t的转换会解析它而uintptr_t就我所理解的而言是等效的。

以下是文件结构的示例

#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
    }
}

感谢您的帮助。我现在看到警告是在调用编译器时未指示正确版本的结果。

1 个答案:

答案 0 :(得分:2)

这个答案很大程度上总结了评论主题的观察和建议,包括我和其他许多人的观点和建议,并将它们包含在一些说明性散文中。

首先,问题出现了,因为当您使用当前工具链构建程序时,以其当前形式,aligned_alloc()函数未显式声明。在没有声明的情况下,编译器推断其签名:它猜测函数返回int,并且其参数类型是通过应用于类型的默认参数促销获得的参数类型实际的论点。然后,编译器会警告您,这些推断 - 尤其是返回类型 - 似乎与您实际使用该函数的方式不一致。

假设该函数在C库中可用,解决方案是确保提供正确的原型。您可以手动插入原型,但您不应该。由于它是一个标准的库函数,你应该从相应的头文件中获取它的声明,对于这个函数是stdlib.h

但是,这个特殊的功能在C11中是新的,显然你正在使用一个默认编译为早期标准的GCC版本。 Glibc通过使用feature-test macro_ISOC11_SOURCE来保护C11中的新功能,从而部分支持。这是为了您的保护:如果您正在构建为早期标准编写的代码,并且该代码恰好提供了与C11新功能之一相同的自己的功能,则功能测试系统可以防止您受到影响名字冲突。

如果你确实在为C11写作,就像这样,如果你的gcc版本有一个支持C11的选项(即-std=c11和/或-std=gnu11),那么编译启用该选项是您的最佳选择。如果您碰巧有一个提供aligned_alloc()但不支持C11模式的编译器版本的Glibc,那么您可以选择手动确保在编译之前为编译器定义所需的功能测试宏包括标准标题。您可以通过源文件顶部的#define或编译器的命令行选项(例如-D_ISOC11_SOURCE=1)来完成此操作。

Glibc 至少从版本2.17开始aligned_alloc()(但我想早在2.16)。至少从版本4.8开始,GCC 具有C11模式。如果这些组件的版本至少是最新的,那么在编译命令中添加选项-std=c11(省略GNU扩展)或-std=gnu11(以支持GNU扩展)应该足够了: / p>

gcc -std=c11 my_program.c