Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/css/35.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 内部定义的外部变量。那么,可执行线索是否有未定义的行为?_C++_Gcc_Linker - Fatal编程技术网

C++ 内部定义的外部变量。那么,可执行线索是否有未定义的行为?

C++ 内部定义的外部变量。那么,可执行线索是否有未定义的行为?,c++,gcc,linker,C++,Gcc,Linker,我在一个遗留代码中工作,我面临一个奇怪的问题。我有一个可执行文件,它使用一个名为dbaccess.so的.so库 我还有一个名为“lib_base”的库,该库静态链接到两个项目(dbaccess.so和可执行文件) 在“dbaccess.so”中的.cpp(clientconn.cpp)中,我有: 我注意到代码中有一些奇怪的行为。看起来“extern”变量混淆了my_应用程序的lib_库中的“apName”定义和dbaccess的lib_库中的定义 使用gdb调试dbaccess函数时,会发生以

我在一个遗留代码中工作,我面临一个奇怪的问题。我有一个可执行文件,它使用一个名为dbaccess.so的.so库

我还有一个名为“lib_base”的库,该库静态链接到两个项目(dbaccess.so和可执行文件)

在“dbaccess.so”中的.cpp(clientconn.cpp)中,我有:

我注意到代码中有一些奇怪的行为。看起来“extern”变量混淆了my_应用程序的lib_库中的“apName”定义和dbaccess的lib_库中的定义

使用gdb调试dbaccess函数时,会发生以下情况:

strcpy( apName, "test" );
printf( apName );
在控制台中,“test”被打印出来,但是如果我在gdb的控制台中strcpy之后写下以下行:

print apName
它打印“apfile.ini”

有人知道这个问题是否真的与“lib_base”与这两个项目相关联?编译dbaccess.so时是否有任何编译标志或可以传递的内容来避免这种情况


我使用linux和gcc作为编译器

如果在.cpp文件中定义了一个变量,而该变量只在该文件中可见,则应使用
static

如果您想在两个库库之间共享值,那么就不应该静态链接它两次-您会得到代码和数据的重复,这既低效又令人困惑

C++有一个叫做“一个定义”的规则,它说你可以定义同一个东西任意多次(因此你可以在多个cpp文件中包含相同的头文件),只要它们都定义相同,它就可以正常工作。基本上,这意味着允许链接器丢弃重复的对象,并随机保留一个。如果您破坏了ODR,编译器将不知道,链接器可能也不知道,然后您将得到未定义的行为

在本例中,您没有破坏ODR,但是您将相同的内容链接到了两个不同的对象(您的应用程序和共享库),这是一个不同的问题。动态链接器(在运行时加载共享库)并不担心这些废话——它所做的只是将应用程序中未定义的符号与其库中的定义连接起来。主应用程序中的apName显然没有未定义,因此动态链接器与此无关,因此这里没有未定义的行为

假设您不希望lib_base的两个实例都共享aPname的定义,那么您的应用程序似乎链接得很好(printf证明了这一点),但是GDB在使用模棱两可的符号名时表现不佳。当GDB查找符号名时,它不一定知道首先要查找的位置,因此您不会得到您期望的符号名

有时,如果您首先执行
listmain
(或其他)来设置所需的上下文,GDB可以自行排序。但基本上,不要重复代码-调试器不会喜欢它


如果必须这样做,请查看
symbol table
addsymbol table
命令-您可以选择仅从一个文件或另一个文件加载符号,并调试所需的位。

是否应该反过来,头文件中的
extern…
声明和源文件中的实际定义?否则,变量将在包含头文件的所有源文件中定义。抱歉,我在编写此问题时出错。我已经编辑了这个问题并修正了它。非常感谢。你需要另一个理由来避免全局变量吗?这是一个遗留代码,我不能更改“lib_base”的内容。我只能在“我的应用程序”和“dbaccess.so”中工作。您是否将可执行文件和.so链接到与
lib\u base
完全相同的版本?您是否碰巧使用了
-b符号
链接标志?
extern char apName[_MAX_FNAME];
strcpy( apName, "test" );
printf( apName );
print apName