声明和定义函数静态会产生“对 function_name() 的未定义引用”
Posted
技术标签:
【中文标题】声明和定义函数静态会产生“对 function_name() 的未定义引用”【英文标题】:Declaring and defining function static yields "undefined reference to function_name()" 【发布时间】:2019-11-21 05:54:48 【问题描述】:这是utils.hpp
中定义的函数原型声明(NON OOP,所以不在任何类中)
static void create_xy_table(const k4a_calibration_t *calibration, k4a_image_t xy_table);
static void generate_point_cloud(const k4a_image_t depth_image,
const k4a_image_t xy_table,
k4a_image_t point_cloud,
int *point_count);
static void write_point_cloud(const char *file_name, const k4a_image_t point_cloud, int point_count);
我在utils.cpp
中有它们的定义,其中包括utils.hpp
。
当我在main.cpp
中调用main
函数中的任何函数时,我收到以下错误:
/tmp/ccFcMfYB.o: In function `main':
main.cpp:(.text+0x208): undefined reference to
`create_xy_table(_k4a_calibration_t const*, _k4a_image_t*)
编译命令:
g++ -o build/testtest src/main.cpp src/utils.cpp -I./include -lk4a
将所有函数定义为非静态并且编译完美!我无法理解这一点。
到底发生了什么? 如果需要定义和链接静态函数,应该怎么做才能正确包含/链接?我的系统配置: gcc 版本 7.4.0 (Ubuntu 7.4.0-1ubuntu1~18.04.1)
编辑: 这是我在 utils.cpp 中的函数定义:
static void create_xy_table(const k4a_calibration_t *calibration, k4a_image_t xy_table)
k4a_float2_t *table_data = (k4a_float2_t *)(void *)k4a_image_get_buffer(xy_table);
int width = calibration->depth_camera_calibration.resolution_width;
int height = calibration->depth_camera_calibration.resolution_height;
k4a_float2_t p;
k4a_float3_t ray;
int valid;
for (int y = 0, idx = 0; y < height; y++)
p.xy.y = (float)y;
for (int x = 0; x < width; x++, idx++)
p.xy.x = (float)x;
k4a_calibration_2d_to_3d(
calibration, &p, 1.f, K4A_CALIBRATION_TYPE_DEPTH, K4A_CALIBRATION_TYPE_DEPTH, &ray, &valid);
if (valid)
table_data[idx].xy.x = ray.xyz.x;
table_data[idx].xy.y = ray.xyz.y;
else
table_data[idx].xy.x = nanf("");
table_data[idx].xy.y = nanf("");
EDIT2:
以下是我在main.cpp
中所做的事情。
k4a_calibration_t calibration;
k4a_image_t xy_table = NULL;
/*
Calibration initialization codes here
*/
create_xy_table(&calibration, xy_table);
【问题讨论】:
编译器错误说明了一切。函数调用有_k4a_image_t*
,但声明有_k4a_image_t
@ThePhilomath:真的吗?请参阅我的问题的编辑部分,我没有像您在评论中所说的那样使用它。此外,为什么声明那些非静态的会解决问题?
@Evg:关于为什么我希望它们是静态的,我真的不需要它们是静态的。我已经制作了那些非静态的并用于我的应用程序。但我想了解发生了什么。您能否详细说明“此编译单元专用”的含义?这里的“编译单元”是什么意思?
至于@ThePhilomath 评论,请出示您的main.cpp
。不清楚为什么它指的是create_xy_table(_k4a_calibration_t const*, _k4a_image_t*)
(注意_k4a_image_t
后面的星号)。
@Evg,请参考 EDIT2 部分的 main.cpp
【参考方案1】:
当您将实现放入单独的编译单元(.cpp
文件)时,您要求链接器稍后在对象文件链接在一起时查找这些实现。当你将一个函数声明为static
时,你说这个函数不应该在其他编译单元中可见(这被称为internal linkage)。
现在,您包含一个带有static
函数的标题。 utils.cpp
将获得它自己的副本,这对于所有其他编译单元都是不可见的。 main.cpp
只会看到声明,而不会看到实现,因此不会生成任何代码。这就是您收到链接错误的原因 - 代码在 utils.cpp
中,但任何人都无法访问。
如果你出于某种原因想要包含static
函数,你应该在头文件中提供它们的实现。然后每个编译单元将获得它们自己的私有副本。
【讨论】:
【参考方案2】:c/c++ 中的静态修饰符将函数定义限制为一个编译单元(utils.cpp)。然后这些函数从其他编译单元不可见/不可访问,例如main.cpp 在你的情况下。
【讨论】:
以上是关于声明和定义函数静态会产生“对 function_name() 的未定义引用”的主要内容,如果未能解决你的问题,请参考以下文章