Page 1 of 1
array and pointer decl's in header file
Posted: Wed Apr 09, 2008 5:45 am
by Neo
If I have a header file with contents as shown below,
Code: Select all
#ifndef __B_H__
#define __B_H__
const char *prt =" string1";
#endif
And now include the above .h in 2 separate CPP files and compile both the CPP files then I get a linkage error.
However using the following works fine,
Code: Select all
#ifndef __B_H__
#define __B_H__
const char prt[] =" string1";
#endif
Would be great if anyone could explain what is causing this?
TIA
Posted: Wed Apr 09, 2008 5:48 am
by Solar
I have a guess, but would like to see
- the (minimal) source files used to reproduce the behaviour,
- the exact compiler options used,
- the exact linker error message.
Out of principle, you know.
Posted: Wed Apr 09, 2008 6:44 am
by Neo
File: b.h
Code: Select all
#ifndef __B_H__
#define __B_H__
const char *prt =" value";
#endif
File: a.cpp
Code: Select all
#include "b.h"
int main()
{
return 0;
}
File:b.cpp
Code: Select all
#include "b.h"
int egFunc(void)
{
return 0;
}
g++ a.cpp b.cpp
/cygdrive/c/DOCUME~1/ABCDE~1/LOCALS~1/Temp/ccCyRYxR.o:b.cpp:(.data+0x0): multiple definition of `_prt'
/cygdrive/c/DOCUME~1/ABCDE~1/LOCALS~1/Temp/cciIrrJR.o:a.cpp:(.data+0x0): first defined here
collect2: ld returned 1 exit status
Posted: Wed Apr 09, 2008 6:55 am
by JamesM
Are array declarations limited to file scope by default?
Posted: Wed Apr 09, 2008 7:10 am
by Solar
Hmmm... fun. I compiled a.cpp to a.o using either version of b.h, and objdump'ed them to find out what's up.
Code: Select all
$ objdump -t a_ptr.o
a_ptr.o: file format pe-i386
SYMBOL TABLE:
[ 0](sec -2)(fl 0x00)(ty 0)(scl 103) (nx 1) 0x00000000 a.cpp
File
[ 2](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000000 _main
[ 3](sec 1)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000 .text
AUX scnlen 0x31 nreloc 2 nlnno 0
[ 5](sec 2)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000 .data
AUX scnlen 0x4 nreloc 1 nlnno 0
[ 7](sec 3)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000 .bss
AUX scnlen 0x0 nreloc 0 nlnno 0
[ 9](sec 4)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000 .rdata
AUX scnlen 0x7 nreloc 0 nlnno 0
[ 11](sec 2)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000 _prt
[ 12](sec 0)(fl 0x00)(ty 20)(scl 2) (nx 1) 0x00000000 ___main
AUX tagndx 0 ttlsiz 0x0 lnnos 0 next 0
[ 14](sec 0)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000 __alloca
Code: Select all
$ objdump -t a_arr.o
a_arr.o: file format pe-i386
SYMBOL TABLE:
[ 0](sec -2)(fl 0x00)(ty 0)(scl 103) (nx 1) 0x00000000 a.cpp
File
[ 2](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000000 _main
[ 3](sec 4)(fl 0x00)(ty 0)(scl 3) (nx 0) 0x00000000 _prt
[ 4](sec 1)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000 .text
AUX scnlen 0x31 nreloc 2 nlnno 0
[ 6](sec 2)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000 .data
AUX scnlen 0x0 nreloc 0 nlnno 0
[ 8](sec 3)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000 .bss
AUX scnlen 0x0 nreloc 0 nlnno 0
[ 10](sec 4)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000 .rdata
AUX scnlen 0x7 nreloc 0 nlnno 0
[ 12](sec 0)(fl 0x00)(ty 20)(scl 2) (nx 1) 0x00000000 ___main
AUX tagndx 0 ttlsiz 0x0 lnnos 0 next 0
[ 14](sec 0)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000 __alloca
As for how the difference is justified, I'm clueless. Which scares be quite somewhat, as I think this is some basics I
should know...
Posted: Wed Apr 09, 2008 7:30 am
by Neo
Just thinking out loud, does it have anything to do with allocation on the stack or heap?
Posted: Wed Apr 09, 2008 8:52 am
by bluecode
well, const char ptr[] creates only an initialised char array and I guess gcc/g++/ld can merge two with the same content nicely. But const char *ptr creates a const char* variable (but the variable itself is not const) pointing to the string. gcc/g++/ld can't merge them cause they are not constant.
Posted: Thu Apr 10, 2008 5:36 am
by Neo
Could this be a compiler bug by any chance?
Posted: Thu Apr 10, 2008 6:03 am
by Solar
Unlikely.
Aside from this being something very basic (and as such highly unlikely to have slipped GCC's quality checks), MSVC++ 8.0 exhibits identical behaviour.
Posted: Thu Apr 10, 2008 6:35 am
by froggey
const char *ptr = "hello"; declares a pointer to const char, equivalent to:
Code: Select all
const char some_array[6] = {'h','e','l','l','o',0};
const char *ptr = some_array;
The string "hello" gets put in rodata and the pointer is put in data and points to the string
const char array[] = "hello"; declares a fixed length array of const char:
Code: Select all
const char array[6] = {'h','e','l','l','o',0};
The array is immutable so can be put in to the rodata section and merged with identical arrays declared in other files
Posted: Thu Apr 10, 2008 1:37 pm
by bluecode
That's exactly what I said/meant, froggey
Posted: Thu Apr 10, 2008 4:24 pm
by froggey
Ah, I completely missed/skimmed over your post
Posted: Fri Apr 11, 2008 1:10 pm
by bluecode
Well, I guess I formulated to unclear/vague...
Posted: Fri Apr 18, 2008 3:48 am
by Neo
Thanks folks.
I've been using C++ for a few years now and still am learning something new all the time.
Posted: Fri Apr 18, 2008 5:31 am
by Neo
Solar wrote:Hmmm... fun. I compiled a.cpp to a.o using either version of b.h, and objdump'ed them to find out what's up.
Code: Select all
$ objdump -t a_ptr.o
a_ptr.o: file format pe-i386
SYMBOL TABLE:
[ 0](sec -2)(fl 0x00)(ty 0)(scl 103) (nx 1) 0x00000000 a.cpp
File
[ 2](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000000 _main
[ 3](sec 1)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000 .text
AUX scnlen 0x31 nreloc 2 nlnno 0
[ 5](sec 2)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000 .data
AUX scnlen 0x4 nreloc 1 nlnno 0
[ 7](sec 3)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000 .bss
AUX scnlen 0x0 nreloc 0 nlnno 0
[ 9](sec 4)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000 .rdata
AUX scnlen 0x7 nreloc 0 nlnno 0
[ 11](sec 2)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000 _prt
[ 12](sec 0)(fl 0x00)(ty 20)(scl 2) (nx 1) 0x00000000 ___main
AUX tagndx 0 ttlsiz 0x0 lnnos 0 next 0
[ 14](sec 0)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000 __alloca
Code: Select all
$ objdump -t a_arr.o
a_arr.o: file format pe-i386
SYMBOL TABLE:
[ 0](sec -2)(fl 0x00)(ty 0)(scl 103) (nx 1) 0x00000000 a.cpp
File
[ 2](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000000 _main
[ 3](sec 4)(fl 0x00)(ty 0)(scl 3) (nx 0) 0x00000000 _prt
[ 4](sec 1)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000 .text
AUX scnlen 0x31 nreloc 2 nlnno 0
[ 6](sec 2)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000 .data
AUX scnlen 0x0 nreloc 0 nlnno 0
[ 8](sec 3)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000 .bss
AUX scnlen 0x0 nreloc 0 nlnno 0
[ 10](sec 4)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000 .rdata
AUX scnlen 0x7 nreloc 0 nlnno 0
[ 12](sec 0)(fl 0x00)(ty 20)(scl 2) (nx 1) 0x00000000 ___main
AUX tagndx 0 ttlsiz 0x0 lnnos 0 next 0
[ 14](sec 0)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000 __alloca
As for how the difference is justified, I'm clueless. Which scares be quite somewhat, as I think this is some basics I
should know...
Just wated to confirm this.
In the first dump the ptr variable is in the .rdata section.
In the second is it in the .text section??