array and pointer decl's in header file

Programming, for all ages and all languages.
Post Reply
User avatar
Neo
Member
Member
Posts: 842
Joined: Wed Oct 18, 2006 9:01 am

array and pointer decl's in header file

Post 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
Only Human
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Post 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. ;-)
Every good solution is obvious once you've found it.
User avatar
Neo
Member
Member
Posts: 842
Joined: Wed Oct 18, 2006 9:01 am

Post 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
Only Human
User avatar
JamesM
Member
Member
Posts: 2935
Joined: Tue Jul 10, 2007 5:27 am
Location: York, United Kingdom
Contact:

Post by JamesM »

Are array declarations limited to file scope by default?
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Post 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...
Every good solution is obvious once you've found it.
User avatar
Neo
Member
Member
Posts: 842
Joined: Wed Oct 18, 2006 9:01 am

Post by Neo »

Just thinking out loud, does it have anything to do with allocation on the stack or heap?
Only Human
User avatar
bluecode
Member
Member
Posts: 202
Joined: Wed Nov 17, 2004 12:00 am
Location: Germany
Contact:

Post 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.
User avatar
Neo
Member
Member
Posts: 842
Joined: Wed Oct 18, 2006 9:01 am

Post by Neo »

Could this be a compiler bug by any chance?
Only Human
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Post 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.
Every good solution is obvious once you've found it.
froggey
Member
Member
Posts: 38
Joined: Tue Oct 17, 2006 10:21 pm
Location: Hampshire, UK

Post 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
User avatar
bluecode
Member
Member
Posts: 202
Joined: Wed Nov 17, 2004 12:00 am
Location: Germany
Contact:

Post by bluecode »

That's exactly what I said/meant, froggey 8)
froggey
Member
Member
Posts: 38
Joined: Tue Oct 17, 2006 10:21 pm
Location: Hampshire, UK

Post by froggey »

Ah, I completely missed/skimmed over your post :)
User avatar
bluecode
Member
Member
Posts: 202
Joined: Wed Nov 17, 2004 12:00 am
Location: Germany
Contact:

Post by bluecode »

Well, I guess I formulated to unclear/vague...
User avatar
Neo
Member
Member
Posts: 842
Joined: Wed Oct 18, 2006 9:01 am

Post by Neo »

Thanks folks.
I've been using C++ for a few years now and still am learning something new all the time. :)
Only Human
User avatar
Neo
Member
Member
Posts: 842
Joined: Wed Oct 18, 2006 9:01 am

Post 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??
Only Human
Post Reply