Fixing "Undefined Reference" Error in .o File

  • Thread starter NeoDevin
  • Start date
  • Tags
    Reference
In summary, this code creates a matrix of pointers to doubles, and attempts to set the first element to 1.0.
  • #1
NeoDevin
334
2
I'm trying to call a function from a .o file, and it keeps telling me:

"undefined reference to ..." where the ... is whatever function I'm trying to call.

Do any of you have any idea what's wrong with this?
 
Technology news on Phys.org
  • #2
How did you compile your code - what command did you use?
A .o file has to be linked into your code (C example)
Code:
cc myfile.c anotherfile.o -o myfile
 
  • #3
I figured it out, I had wrong capitalization of the function name.

Next question:

If I have a pointer to the first element of a dynamically allocated 2 dimension array, is there any way to use two subscripts with that pointer.
Code:
//I create a dynamically allocated array:
int i;
int N = 100;
double **A;
double *p;
A = new double *[N]
for(i = 0; i < N; i++) A[i] = new double [N];

// and point a pointer to the first element.
p = A[0];

//now I want to be able to use it like this:

p[3][4] = 12;
 
  • #4
C really has no concept of multi-dimensional arrays; all arrays are really stored in a one-dimensional format in memory. When you want to access element [3][4], the compiler actually performs some math to get a one-dimensional index: 3 * (number of elemts in row) + 4. If the compiler doesn't know how many elements are in a row, it cannot do this.

So, if all you're given is a pointer to the first element of a multidimensional array, you are effectively screwed.

- Warren
 
  • #5
There's no way to typecast it, if you know the number of elements in the row?
 
  • #6
Your code creates an array of pointers, this is not a matrix.

In the matrix examples below, note that "double (*pmd)[5]" declares pmd to be a pointer to an array of 5 doubles,
as opposed to "double *pmd[5]" which is an array of 5 pointers to double; the parenthesis around *pmd is what makes the difference.

C++ matrix example:

Code:
    double (*pmd)[5] = new double[4][5];
    pmd[1][2] = 1.0;
    delete [] pmd;

C++ array with matrix typecast example:
Code:
    double *pad = new double[20];
    ((double (*)[5])pad)[1][2] = (double) 1.0;
    delete []pad;

C matrix:
Code:
    double (*pmd)[5] = (void *)malloc(4*5*sizeof(double));
    pmd[1][2] = 1.0;
    free(pmd);

C array with matrix typecast:

Code:
    double *pad = (void *)malloc(4*5*sizeof(double));
    ((double (*)[5])pad)[1][2] = 1.0;
    free((void *)pad);

Using Microsoft compiler, all 3 examples produce essentially the same code:
allocate 160 bytes,
set [ptr+56] = [ptr + (((1 x 5) + 2) x sizeof(double))] to 1.0
free ptr.
 
Last edited:
  • #7
Jeff Reid said:
Code:
    double (*pmd)[5] = new double[4][5];
    pmd[1][2] = 1.0;
    delete [] pmd;

Can you do this if you need both dymensions to be dynamically allocated?

Jeff Reid said:
C++ array with matrix typecast example:
Code:
    double *pad = new double[20];
    ((double (*)[5])pad)[1][2] = (double) 1.0;
    delete []pad;

This is what I was looking for. Thank you.
 
  • #8
NeoDevin said:
Can you do this if you need both dimensions to be dynamically allocated?
Not with the Microsoft compilers. Only the first dimension of a muti-dimensional array is allowed to be dynamic, the rest have to be compile time constants. You would need to use a vector of pointers to accomplish the equivalent, and would have to iterate for each allocation and/or freeing of a vector. The entity would be a mix of pointers and doubles.

In the examples above, what I really created was a pointer to an vector of 5 doubles, such as "double (*pv)[5]". C and C++ allow pv[j] or (*pv+i)[j], effectively promoting the pointer to a vector to a pointer to a matrix.

For a more familiar example, "double *ps" is a pointer to a scalar double (just one instance), and C and C++ allow ps or *(ps+i), effectively promoting the pointer to a scalar to a pointer to a vector.

Here is an example that actually uses a pointer to a matrix:
Code:
    static double *ps = new double[40];         // poitner to scalar
    double (*pv)[5] = (double (*)[5])ps;        // pointer to vector
    double (*pm)[4][5] = (double (*)[4][5])ps;  // pointer to matrix
    ps[6] = 1.0;                                // *(ps +  6) = 1.0
    pv[1][2] = 1.0;                             // *(ps +  7) = 1.0
    (*pm)[3][4] = 1.0;                          // *(ps + 19) = 1.0
    pm[1][2][3] = 1.0;                          // *(ps + 33) = 1.0
    delete [] ps;
 
Last edited:
  • #9
Jeff Reid said:
Not with the Microsoft compilers. Only the first dimension of a muti-dimensional array is allowed to be dynamic, the rest have to be compile time constants.

In the examples above, what I really created was a pointer to an vector of 5 doubles, such as "double (*pv)[5]". C and C++ allow pv[j] or *(pv+i)[j], effectively promoting the pointer to a vector to a pointer to a matrix.

As an analogy, "double *ps" is a pointer to a scalar double (just one instance), and C and C++ allow ps or *(ps+i), effectively promoting the pointer to a scalar to a pointer to a vector.

Here is an example that actually uses a pointer to a matrix:
Code:
    static double *ps = new double[40];         // poitner to scalar
    double (*pv)[5] = (double (*)[5])ps;        // pointer to vector
    double (*pm)[4][5] = (double (*)[4][5])ps;  // pointer to matrix
    ps[6] = 1.0;                                // *(ps +  6) = 1.0
    pv[1][2] = 1.0;                             // *(ps +  7) = 1.0
    (*pm)[3][4] = 1.0;                          // *(ps + 19) = 1.0
    pm[1][2][3] = 1.0;                          // *(ps + 33) = 1.0
    delete [] ps;


My code from post 3 works to create a two dimensional dynamically allocated array. Try it. I don't understand why you tell me that it doesn't work.

Code:
//next two lines create a dynamically allocated N by M array A[N][M]
double **A = new double *[N];
for(i = 0; i < N; i++) A[i] = new double[M];

//we can then use it like this
A[1][3] = 14;
cout << A[1][3];

What I was asking was not how to create the array (though if there is a better way, I'd be glad to hear it, this method always seemed inelegant to me), but if I later have a pointer pointing to the first element of the array, how to use it with two subscripts.

Code:
//make a pointer and point it to the first element of A
double *p;
p = A[0];

//I wanted to be able to use p something like p[1][3]
//you gave me the answer by typecasting the pointer

((double (*)[M])p)[1][3] = 14;
cout << ((double (*)[M])p)[1][3];
 
  • #10
You are talking past one another, thanks to how C (and C++) treats multi-dimensional and ragged arrays. Jeff Reid is creating multi-dimensional arrays while NeoDevin is creating ragged arrays. A multi-dimensional array occupies a monolithic block of memory and is allocated by a single new/malloc, while a ragged array comprises multiple chunks of memory and requires multiple new/malloc invocations. Both are accessed the same way: [noparse]multi_dim_array[index1][index2][/noparse] versus [noparse]ragged_array[index1][index2][/noparse].
 
  • #11
NeoDevin said:
If I have a pointer pointing to the first element of the array, how to use it with two subscripts.
You can't. You need a pointer to one of the pointers in A in order to use two subscripts. If you just copy the first pointer in A to a pointer to double, "p = A[0]", there's no way to get to A[1], A[2], ..., from p, because the vector of pointers only exists in A, while p only contains a single pointer. You'd have to create a duplicate of A, a pointer to a pointer to a double. You can implement this with just two allocated chunks of memory, by allocating a large vector, then setting A[] to sequentially higher locations in the large vector:
Code:
int main()
{
    int i0, i1;                         // indexes
    int d0, d1;                         // dimension sizes

    d0 = 4;
    d1 = 5;

    double **apd = new double *[d0];    // allocate vector of pointers
    double *pd = new double[d0*d1];     // allocate large vector of doubles

    double *pt = pd;                    // temp pointer to vector of doubles
    for(i0 = 0; i0 < d0; i0++){         // set pointers to vectors of doubles
        apd[i0] = pt;
        pt += d1;}

    double **ppd = apd;                 // copy of apd;

    for(i0 = 0; i0 < d0; i0++)          // access the data
        for(i1 = 0; i1 < d1; i1++)
            ppd[i0][i1] = 1.0*i0*i1;

    delete [] pd;                       // delete large vector of doubles
    delete [] apd;                      // delete vector of pointers
    return(0);
}


D H said:
You are talking past one another, thanks to how C (and C++) treats multi-dimensional and ragged arrays. Jeff Reid is creating multi-dimensional arrays while NeoDevin is creating ragged arrays.
I already mentioned this in post #6: "Your code creates an array of pointers, this is not a matrix."
 
Last edited:

What is an "Undefined Reference" error in a .o file?

An "Undefined Reference" error occurs when the linker is unable to find the definition of a symbol referenced in the object file. This could be due to a missing or incorrect library, function, or variable declaration.

How can I fix an "Undefined Reference" error?

The first step is to check the object file for any missing or incorrect declarations. Make sure all necessary libraries are included and that function and variable names are spelled correctly. If the error persists, try using the linker's verbose mode to get more information on the specific symbol causing the error.

Why am I getting an "Undefined Reference" error in my .o file?

There could be several reasons for this error, including missing or incorrect declarations, using a different compiler or linker than the one used to create the object file, or using incompatible versions of libraries. It is important to carefully check all of these factors when troubleshooting the error.

Can I prevent "Undefined Reference" errors in my .o file?

While it is not always possible to prevent these errors, there are some steps you can take to minimize the chances of encountering them. These include carefully checking all declarations, using the same versions of libraries and compilers, and regularly testing and debugging your code to catch any potential errors early on.

Is an "Undefined Reference" error in a .o file always caused by a missing declaration?

Not necessarily. While a missing or incorrect declaration is a common cause of these errors, there could be other reasons such as a corrupted object file or incorrect compiler/linker settings. It is important to thoroughly investigate all possible causes when troubleshooting this error.

Similar threads

  • Programming and Computer Science
Replies
2
Views
364
Replies
1
Views
1K
  • Programming and Computer Science
Replies
21
Views
508
  • Programming and Computer Science
Replies
25
Views
2K
  • Programming and Computer Science
Replies
6
Views
8K
  • Programming and Computer Science
Replies
8
Views
1K
  • Programming and Computer Science
Replies
1
Views
576
  • Programming and Computer Science
Replies
17
Views
4K
  • Programming and Computer Science
Replies
8
Views
2K
  • Programming and Computer Science
Replies
10
Views
1K
Back
Top