Perhaps you are seeing the Procedure Linkage Table (PLT) address from a shared library function on Unix?
The compiler builds a table of 'trampoline' addresses that indirectly refer to the shared library dependencies. It is a complicated topic, there is a detailed article here
Here is a simple example.
lib.cpp
#include <iostream>
int foo()
{
return 0;
}
junk.cpp
#include<iostream>
int foo();
int main(int argc, char* argv[])
{
int k = foo();
return 0;
}
Compile
/tmp$ g++ -fPIC -g -std=c++11 -shared -o libtest_library.so lib.cpp
/tmp$ g++ -g -std=c++11 -o tramp junk.cpp -L . -l test_library
gdb tramp
Reading symbols from tramp...done.
(gdb) p foo
$1 = (<text from jump slot in .got.plt, no debug info>) 0x4006d6 <foo()@plt+6>
(gdb) b foo
Breakpoint 1 at 0x4006d0
(gdb) d 1
(gdb) r
Starting program: /tmp/tramp
lib: 0x602010
[Inferior 1 (process 12804) exited normally]
(gdb) b foo
Breakpoint 2 at 0x4006d0 (2 locations)
(gdb) info break
Num Type Disp Enb Address What
2 breakpoint keep y <MULTIPLE>
2.1 y 0x00000000004006d0 <foo()@plt>
2.2 y 0x00002aaaaacd0a99 in foo() at lib.cpp:6
As you can see the symbol 'foo' has two addresses and two breakpoints. One is the PLT and the other the symbol location in the shared library.
As the comments noted, template instantiations and compiler optimizations can also create multiple addresses for one symbol or source line.