2
/* my program
   author/date:  me/now
*/

# include <stdio.h>

# define XX    1000
# define YY    20000       /* value of 1000 is ok */
# define ZZ    6000

/* global variable declaration */

int some_variable_this;
int some_variable_that;
double data[XX][YY][ZZ];

static void some_procedure_this ( void )
{
}

static void some_procedure_that ( void )
{
}

int main ( int argc, char *argv[] )
{
}

writing a quick C program to reformat some data. when compiling via gcc myprogram.c if I make the global data array too large I get the compiler error:

relocation truncated to fit R_X86_64_PC32 against symbol 'some_variable_this'
relocation truncated to fit R_X86_64_PC32 against symbol 'some_variable_that'

My goal is to do a quick c code to reformat some data.

  • What does this R_X86_64_PC32 mean?
  • Is there a compiler flag I can used to get around this?
  • Is there a better way to code this, in C, while still maintaining quickness of writing the code and simplicity for human readability?

this on gcc 4.3.4 in linux if it matters.

ron
  • 967
  • 6
  • 23
  • Why are `this` and `that` declared as both `int`s and `void` functions? – Christian Gibbons Aug 02 '19 at 19:07
  • I stripped the program to post it, and figured folks would be able to read past *this* and *that* and get the understanding this are other lines in the code – ron Aug 02 '19 at 19:09
  • assuming *this* and *that* is not relevant to my questions – ron Aug 02 '19 at 19:09
  • 4
    Note that `1000 * 20000 * 6000 * sizeof(double)` is only a tad short of 1 TiB main memory. It is kinda large for an array. Are you sure the size is appropriate? I'm mildly jealous if you actually do have a machine with a terabyte of main memory. – Jonathan Leffler Aug 02 '19 at 19:10
  • 512gb on *this_server*, 1.5tb on *that_server* – ron Aug 02 '19 at 19:12
  • hoping to write a quick c code, not write it in *ISO_this* and *ISO_that* standards to perfection. I want the money spent on all this RAM to save me time. – ron Aug 02 '19 at 19:14
  • 1
    You say that `1000` is OK but `20000` is not. Methinks the size of that array is a major factor in your problem. Can you use dynamic memory allocation (`malloc()` et al) to avoid the enormous statically sized array? – Jonathan Leffler Aug 02 '19 at 19:14
  • hoping to not use `malloc` and just static clear a 3 dimensional array... maybe 5 dimension, to hold a bunch of data, do some math, print out in different order. Using malloc i gotta do all the index calculations, it's friday i don't wanna do that... wanted this done an hour ago... – ron Aug 02 '19 at 19:17
  • 1
    `double (*data)[YY][ZZ] = 0` defines a pointer to an array (and if there's more than one source file, a header declares `extern double (*data)[YY][ZZ];` — which means (`XX` and) `YY` and `ZZ` will be defined in the header too). In your `main()` program, add `data = malloc(XX * YY * ZZ * sizeof(double)); if (data == 0) { …allocation failed… }` to allocate the memory. The rest of the code that uses the array doesn't need to change a bit. – Jonathan Leffler Aug 02 '19 at 19:19
  • 1
    You might find it appropriate to use `calloc()` instead of `malloc()` to ensure that the memory is zeroed before use. Also note that even if you can zero memory at a rate of 4 GHz and set 8 bytes (64 bits) per clock cycle, it is still going to take around 30 seconds to just zero that much memory. Nothing is going to be fast on that array. – Jonathan Leffler Aug 02 '19 at 19:24
  • Do you in fact get the error you describe with the example code presented in the question? I don't have GCC 4.3 readily available to me, but your program does not give me any such diagnostic when built with GCC 4.8.5. – John Bollinger Aug 02 '19 at 19:45
  • I'd guess that R_X86_64_PC32 means 32-bit PC-relative addressing on x86-64 architecture. As a test, you could move the declaration of `some_variable_that` after the oversized array, and see if one of the error messages goes away. – user3386109 Aug 02 '19 at 19:53

1 Answers1

3
  • What does this R_X86_64_PC32 mean?

It is an ELF relocation type used in ELF for x86_64. This particular type expresses that the location of the referenced data is computed based on a 32-bit offset from the an address related to the program counter. I interpret the diagnostics to indicate that the needed offsets are too large to fit in the provided 32 bits, which means that the compiler generated code that, in practice, the linker wasn't able to link correctly.

  • Is there a compiler flag I can used to get around this?

Maybe. The basic problem is that you've defined an object that is larger than the authors of your compiler imagined (at the time) that anyone would be able to accommodate. You're going beyond its design limits.

There may be options that would mitigate this effect. In particular, you could try twiddling the -fPIC and / or -fPIE options, and there may be others.

  • Is there a better way to code this, in C, while still maintaining quickness of writing the code and simplicity for human readability?

It's not a C problem per se, it's an implementation problem. Yet GCC is not wrong or faulty here as far as the language standard is concerned -- the standard does not obligate implementations to accept every possible program that is technically valid.

With that said, you could also try moving the declarations of some_variable_this and some_variable_that after the declaration of data. Conceivably, it might also help to declare those variables static, or to move them (or data) to a separate shared library.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
  • thanks. I'm guessing at this point with > 1TB of shared memory servers becoming more available my old ways of simply defining `double myarray [HUGE];` in the ( data segment ?) can't be done anymore. The only reliable way, in C, is use `malloc()` and `calloc()` ? – ron Aug 05 '19 at 14:21