Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

cannot access array defined in external file, W/O the keyword "extern"

Tags:

c++

arrays

c

I discover that no matter how, I cannot access an array defined in an external file. So I do some simple test like these in both c and c++:

In C:

main.c

#include<stdio.h>
#include<string.h>
#include<stdlib.h>

int func();
char arr[100]="";

int main()
{
  for(int i=0;i<=9;++i){
    func();
    printf("%s\n",arr);
  }
return 0;
}

func.c

#include<string.h>
#include<stdio.h>

extern char* arr;
int func(){
  strcat(arr,"hello");          // try to access arr here
  return 0;
}

In C++:

main.cpp

#include<iostream>
using namespace std;

int func();
char arr[100]="";

int main()
{
  for(int i=0;i<=10;++i){
    func();
    cout<<arr<<endl;
  }
return 0;
}

func.cpp

#include<cstring>
extern char* arr;

int func(){
  strcat(arr,"hello");      // try to access arr here

  return 0;
}

Pretty simple test as you can see. No matter what method I use to access an array in an external file, I got segmentation fault.

like image 209
walkerlala Avatar asked Mar 16 '23 19:03

walkerlala


1 Answers

Variable linking isn't type-safe.

The problem is that you're defining the name "arr" to refer to an array.
Assuming that the array is located at address 0x10, it looks something like this:

Address     0x10  0x11  0x12  0x13
Content    |  0  |  0  |  0  |  0 | (... 100 zeroes in total)

The name "arr" refers to the location where this array is stored.

In "func.cpp" (and "func.c" - they work exactly the same) you claim, or declare, that the name "arr" refers to a pointer.
This is a lie because it is not what you defined it to be, but the compiler and the linker blindly trust you.

This lie causes the code in func to interpret the value stored at the address 0x10 as a pointer instead of an array.
With 32-bit pointers, that would be

Address  0x10   0x14
Content |  0  |  0  | (...)

And when you strcat onto 0, things don't go well.

If you store something more distinct than zeroes in the array (e.g. "\1\2\3\4") and examine the pointer in a debugger, it will be more obvious that the array's elements have "become" the pointer's value.

The fix is to make the proper claim; that arr is an array:

extern char arr[];

(Note that in variable declarations, as opposed to function parameters, char arr[] is not the same as char* arr.)

like image 172
molbdnilo Avatar answered Apr 27 '23 13:04

molbdnilo