【问题标题】:Undefined reference to 'printf' in C programC程序中对'printf'的未定义引用
【发布时间】:2017-06-23 09:25:07
【问题描述】:

我正在尝试了解一些gcc 功能,例如__attribute__,更准确地说,是如何使用__attribute__((__section__("foo"))) 在特定内存位置分配数据/代码。

我的设置

align.c

#include <stdio.h>
//Align some ints
#define BYTES 16
#define __weird_thing __attribute__((__section__("weird.data")))
int __weird_thing *bootstrap;
int a __attribute__((aligned(BYTES))) = 1;
int b __attribute__((aligned(BYTES))) = 2;
int c = 3;
int d __attribute__((aligned(BYTES))) = 4;


int main( int argc, char *argv[])
{
        extern a, b, c, d;
        int *p = &a;
        printf(" a = %p \n", &a);
        printf(" sizof(a) = %d\n", sizeof(a));
        printf("__alignof__ = %d\n", __alignof__(a));
        printf(" p = %p \n\n", p);

        printf(" b = %p \n", &b);
        printf(" sizof(b) = %d\n", sizeof(b));
        printf("__alignof__ = %d\n", __alignof__(b));
        p = p + (BYTES / sizeof(int));
        printf(" p = %p \n\n", p);

        printf(" c = %p \n", &c);
        printf(" sizof(c) = %d\n", sizeof(c));
        printf("__alignof__ = %d\n", __alignof__(c));
        p = p + sizeof(b) / sizeof(int) ;
        printf(" p = %p \n\n", p);

        long unsigned int alignment;
        for(;(alignment=( (long unsigned int) p) & (BYTES << 1 )- 1 ,    printf("alignment = %p\n",alignment), alignment  != 0 ) ; p++);
        printf(" d = %p \n", &d);
        printf(" sizof(d) = %d\n", sizeof(d));
        printf("__alignof__ = %d\n", __alignof__(d));
        printf(" p = %p \n\n", p);
}

包括/不可能.h

int imposible(void);

不可能的.c

#include<imposible.h>
extern unsigned long int base;
int imposible(void)
{
        base++;
        return (int) &base;
}

ld.lds

SECTIONS
{
        . = 0x10000;
        weird.data : { *(weird.data) }
        base = .;
}

问题

每当我尝试链接时,它都会因未定义的引用而失败

dudarev@Test-Sandbox section $ gcc -c align.c -o align.o
dudarev@Test-Sandbox section $ gcc -c -I include/ imposible.c -o imposible.o
imposible.c: In function ‘imposible’:
imposible.c:6:9: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
  return (int) &base;
     ^

dudarev@Test-Sandbox section $ ld -T ld.lds align.o imposible.o -o a.out
align.o: In function `main':
align.c:(.text+0x27): undefined reference to `printf'
align.c:(.text+0x3b): undefined reference to `printf'
align.c:(.text+0x4f): undefined reference to `printf'
align.c:(.text+0x65): undefined reference to `printf'
align.c:(.text+0x79): undefined reference to `printf'
align.o:align.c:(.text+0x8d): more undefined references to `printf' follow

据我所知,它没有找到 printf,这意味着 stdio 没有链接。 我在this stackoverflow 问题之后安装了glibc-static,并尝试了-lcld 的切换,最终结果是

dudarev@Test-Sandbox section $ ld -lc -T ld.lds align.o imposible.o -o a.out
ld: cannot find -lc

我错过了什么?

提前致谢

【问题讨论】:

  • 尝试使用详细标志-v 在同一个文件(而不是ld)上运行gcc,并查看所有传递给ld(或collect2)的标志。
  • 同样不相关但return (int) &amp;base;。为什么?
  • @AjayBrahmakshatriya,这是输出pastebin.com/3w8Y4b62
  • @AjayBrahmakshatriya,对于不相关的,如上所述,我正在学习,我正在尝试使用 base 检索节指针地址。
  • 是什么让你认为将指针投射到int 会给你节指针(不管那是什么)?

标签: c gcc linker ld


【解决方案1】:

关于这个问题:

imposible.c:6:9: 警告:从指针转换为不同大小的整数 [-Wpointer-to-int-cast] return (int) &base;

这是因为'base'是类型:long int,而imposible()函数的返回类型是:int

文件align.c 导致编译器输出大量警告,所有这些都应该被纠正。

文件:ld.lds 缺少几个必要的语句。

ld.lds 的缺失语句是找不到printf() 函数的原因

这是align.c 文件的更正版本

#include <stdio.h>

//Align some ints
#define BYTES 16

#define weird_thing __attribute__((__section__("weird.data")))
int weird_thing *bootstrap;

int a __attribute__((aligned(BYTES))) = 1;
int b __attribute__((aligned(BYTES))) = 2;
int c = 3;
int d __attribute__((aligned(BYTES))) = 4;


int main( void )
{
        extern int a;
        extern int b;
        extern int c;
        extern int d;
        int *p = &a;
        printf(" a = %p \n", (void*)&a);
        printf(" sizof(a) = %lu\n", sizeof(a));
        printf("__alignof__ = %lu\n", __alignof__(a));
        printf(" p = %p \n\n", p);

        printf(" b = %p \n", &b);
        printf(" sizof(b) = %lu\n", sizeof(b));
        printf("__alignof__ = %lu\n", __alignof__(b));
        p = p + (BYTES / sizeof(int));
        printf(" p = %p \n\n", p);

        printf(" c = %p \n", &c);
        printf(" sizof(c) = %lu\n", sizeof(c));
        printf("__alignof__ = %lu\n", __alignof__(c));
        p = p + sizeof(b) / sizeof(int) ;
        printf(" p = %p \n\n", p);

        long unsigned int alignment;
        for( ;
             (alignment = (long unsigned int) p) &
             ((BYTES << 1 )- 1) && alignment != 0 ;
             p++)
        {
             printf("alignment = %p\n", (void*)alignment);
        }

        printf(" d = %p \n", &d);
        printf(" sizof(d) = %lu\n", sizeof(d));
        printf("__alignof__ = %lu\n", __alignof__(d));
        printf(" p = %p \n\n", p);
}

仅编译/链接 align.c 文件然后运行会产生以下结果:(在我的 linux 计算机上,没有 ld.lds 文件)

a = 0x602070 
 sizof(a) = 4
__alignof__ = 16
 p = 0x602070 

 b = 0x602080 
 sizof(b) = 4
__alignof__ = 16
 p = 0x602080 

 c = 0x602084 
 sizof(c) = 4
__alignof__ = 4
 p = 0x602084 

alignment = 0x602084
alignment = 0x602088
alignment = 0x60208c
alignment = 0x602090
alignment = 0x602094
alignment = 0x602098
alignment = 0x60209c
 d = 0x602090 
 sizof(d) = 4
__alignof__ = 16
 p = 0x6020a0 

注意:align.c 文件有 main() 函数,它不会调用任何其他已发布的函数,例如 imposible()

【讨论】:

  • 能否请您指出链接描述文件中缺少哪些必要的语句以及为什么它们是访问 printf 所必需的?
  • @Ruso_x,.lds 文件必须包含“独立”的库并包含“printf()”函数的实现
猜你喜欢
  • 1970-01-01
  • 2013-01-27
  • 2016-03-26
  • 1970-01-01
  • 2019-07-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多