# Cannot use simplest ifstream with LAPACK

Tags:
1. Jun 6, 2015

### Angelos K

I have an official LAPACK example from here:

https://software.intel.com/sites/pr.../mkl_sa/11/mkl_lapack_examples/dsyev_ex.c.htm

It compiles and runs without errors or warnings after using

ludi@ludi-M17xR4:~/Desktop/tests$gcc -Ddsyev=dsyev_ -o sylapack sylapack.c -L/usr/local/lib -llapack -lblas && ./sylapack​ Then, I have a very simple programme using ifstream for reading from a file into a vector. It, too, compiles flawlessly using ludi@ludi-M17xR4:~/Desktop/tests$ g++ -Wall -pedantic -o justread.x justread.cc && ./justread.x

Here is the latter programme:
#include <fstream>
#include <vector>

{
std::vector<double> data;
double tmp;

std::ifstream fin("peano_covariance.data");

while(fin >> tmp)
{
data.push_back(tmp);
}

return 0;
}

int main()
{
return 0;
}​

I just want to use read_covariance() from the small programme within the first programme. To that end I just modify the start of the LAPACK example, adding the function I want to use. Explicitly, I moddify just the start of the example to

#include <stdlib.h>
#include <stdio.h>
#include <fstream>
#include <vector>

{
std::vector<double> data;
double tmp;

std::ifstream fin("peano_covariance.data");

while(fin >> tmp)
{
data.push_back(tmp);
}

return 0;
}

/* DSYEV prototype */
extern void dsyev( char* jobz, char* uplo, int* n, double* a, int* lda,
double* w, double* work, int* lwork, int* info );
/* Auxiliary routines prototypes */
extern void print_matrix( char* desc, int m, int n, double* a, int lda );

/* Parameters */​

Leaving it otherwise unmodified. I added some unmodified lines to make clear where I am. I immediately get a ton of errors:

ludi@ludi-M17xR4:~/Desktop/tests$gcc -Ddgeev=dgeev_ -o combo combo.cc -L/usr/local/lib -llapack -lblas && ./combo combo.cc: In function ‘int main()’: combo.cc:107:74: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings] dsyev( "Vectors", "Upper", &n, a, &lda, w, &wkopt, &lwork, &info ); ^ combo.cc:107:74: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings] combo.cc:111:72: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings] dsyev( "Vectors", "Upper", &n, a, &lda, w, work, &lwork, &info ); ^ combo.cc:111:72: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings] combo.cc:118:49: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings] print_matrix( "Eigenvalues", 1, n, w, 1 ); ^ combo.cc:120:72: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings] print_matrix( "Eigenvectors (stored columnwise)", n, n, a, lda ); ^ /tmp/ccZrNqc0.o: In function read_covariance()': combo.cc:(.text+0x3f): undefined reference to std::basic_ifstream<char, std::char_traits<char> >::basic_ifstream(char const*, std::_Ios_Openmode)' combo.cc:(.text+0x73): undefined reference to std::istream:perator>>(double&)' combo.cc:(.text+0x88): undefined reference to std::basic_ios<char, std::char_traits<char> >:perator void*() const' combo.cc:(.text+0xa6): undefined reference to std::basic_ifstream<char, std::char_traits<char> >::~basic_ifstream()' combo.cc:(.text+0xda): undefined reference to std::basic_ifstream<char, std::char_traits<char> >::~basic_ifstream()' /tmp/ccZrNqc0.o: In function main': combo.cc:(.text+0x1af): undefined reference to dsyev(char*, char*, int*, double*, int*, double*, double*, int*, int*)' combo.cc:(.text+0x236): undefined reference to dsyev(char*, char*, int*, double*, int*, double*, double*, int*, int*)' /tmp/ccZrNqc0.o: In function std::vector<double, std::allocator<double> >::_M_insert_aux(__gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > >, double const&)': combo.cc:(.text._ZNSt6vectorIdSaIdEE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPdS1_EERKd[_ZNSt6vectorIdSaIdEE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPdS1_EERKd]+0x263): undefined reference to __cxa_end_catch' combo.cc:(.text._ZNSt6vectorIdSaIdEE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPdS1_EERKd[_ZNSt6vectorIdSaIdEE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPdS1_EERKd]+0x276): undefined reference to __cxa_begin_catch' combo.cc:(.text._ZNSt6vectorIdSaIdEE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPdS1_EERKd[_ZNSt6vectorIdSaIdEE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPdS1_EERKd]+0x2df): undefined reference to __cxa_rethrow' /tmp/ccZrNqc0.o: In function std::vector<double, std::allocator<double> >::_M_check_len(unsigned long, char const*) const': combo.cc:(.text._ZNKSt6vectorIdSaIdEE12_M_check_lenEmPKc[_ZNKSt6vectorIdSaIdEE12_M_check_lenEmPKc]+0x4c): undefined reference to std::__throw_length_error(char const*)' /tmp/ccZrNqc0.o: In function __gnu_cxx::new_allocator<double>::deallocate(double*, unsigned long)': combo.cc:(.text._ZN9__gnu_cxx13new_allocatorIdE10deallocateEPdm[_ZN9__gnu_cxx13new_allocatorIdE10deallocateEPdm]+0x1c): undefined reference to operator delete(void*)' /tmp/ccZrNqc0.o: In function __gnu_cxx::new_allocator<double>::allocate(unsigned long, void const*)': combo.cc:(.text._ZN9__gnu_cxx13new_allocatorIdE8allocateEmPKv[_ZN9__gnu_cxx13new_allocatorIdE8allocateEmPKv]+0x2c): undefined reference to std::__throw_bad_alloc()' combo.cc:(.text._ZN9__gnu_cxx13new_allocatorIdE8allocateEmPKv[_ZN9__gnu_cxx13new_allocatorIdE8allocateEmPKv]+0x3c): undefined reference to operator new(unsigned long)' /tmp/ccZrNqc0.o:(.eh_frame+0x4b): undefined reference to __gxx_personality_v0' collect2: error: ld returned 1 exit status ludi@ludi-M17xR4:~/Desktop/tests$

Can anyone offer guidance??

Last edited: Jun 6, 2015
2. Jun 6, 2015

### D H

Staff Emeritus
Emphasis mine:
That you are compiling and linking with gcc (rather than g++) explains a large number of your errors. The problem is that gcc doesn't know to use the standard library. g++ does. So use g++. After all, you are writing c++, not c.

The remaining warnings will be just that, warnings. The C wrapper to the fortran function dsyev is ancient. Strictly speaking, it's illegal to pass something like "Vector" as a char*. The compiler is warning you about that.

3. Jun 6, 2015

### Angelos K

Thank you so much!! What you say is so logical and resolves many errors. But there are still some errors left:

ludi@ludi-M17xR4:~/Desktop/tests$g++ -Ddsyev=dsyev_ -o combo.x combo.cc -L/usr/local/lib -llapack -lblas && ./combo.x combo.cc: In function ‘int main()’: combo.cc:107:74: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings] dsyev( "Vectors", "Upper", &n, a, &lda, w, &wkopt, &lwork, &info ); ^ combo.cc:107:74: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings] combo.cc:111:72: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings] dsyev( "Vectors", "Upper", &n, a, &lda, w, work, &lwork, &info ); ^ combo.cc:111:72: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings] combo.cc:118:49: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings] print_matrix( "Eigenvalues", 1, n, w, 1 ); ^ combo.cc:120:72: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings] print_matrix( "Eigenvectors (stored columnwise)", n, n, a, lda ); ^ /tmp/cciDZkcq.o: In function main': combo.cc:(.text+0x1af): undefined reference to dsyev_(char*, char*, int*, double*, int*, double*, double*, int*, int*)' combo.cc:(.text+0x236): undefined reference to dsyev_(char*, char*, int*, double*, int*, double*, double*, int*, int*)' collect2: error: ld returned 1 exit status ludi@ludi-M17xR4:~/Desktop/tests$​

4. Jun 6, 2015

### Angelos K

All errors disappeared by using C linkage. Every occurrence of

extern void function
{...}

was replaced by

extern "C"
{
void function
{...}
}

Specifically, I now use:
/* DSYEV prototype */
extern "C"{
void dsyev( char* jobz, char* uplo, int* n, double* a, int* lda,
double* w, double* work, int* lwork, int* info );
}
/* Auxiliary routines prototypes */
extern "C"{
void print_matrix( char* desc, int m, int n, double* a, int lda );
}
I kind of understand what extern "C" does. Could someone explain what extern did? Was it spurious?

The warnings I still get are all of the type.

combo.cc:110:74: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
dsyev( "Vectors", "Upper", &n, a, &lda, w, &wkopt, &lwork, &info );
^
combo.cc:110:74: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
I think they are no big deal, but if someone knows how to remedy them...

Last edited: Jun 6, 2015
5. Jun 7, 2015

### Staff: Mentor

According to some documentation I found for dsyev (http://www.math.utah.edu/software/lapack/lapack-d/dsyev.html), there is a mismatch between your actual arguments (in the call to dsyev()) and the parameters that are described in the documentation.

Here's a comparison between the input formal parameters you show in the dsyev prototype above, and those described in the documentation:
Code (Text):

Parameter Your prototype.................Docs I found
jobz (in)       char *            CHARACTER* 1 <--- This is a single character, not a pointer
uplo (in)       char *            CHARACTER*1 <---- Ditto
n (in)          int *             INTEGER  <--- In your prototype, n is a pointer; in the docs it's an integer, which is not the same.
LDA (in)        int *             INTEGER  <--- Ditto
LWORK (in)      int *             INTEGER <--- Ditto
I didn't list the in/out or out parameters, which do need to be pointers when you're calling this routine from C or C++. The in parameters shouldn't be pointers (addresses) as you have them. Since the parameters you show in your prototype agree with the types you show in the call to dsyev, I don't believe that the compiler will issue a warning, but it seems likely to me that you'll get very inaccurate results. This business of the parameters is the same thing I said in the other thread you posted, so it doesn't seem to have stuck with you.

The two warnings you show come from using string constants in your calls to dsyev (e.g., "Vectors" and "Upper") instead of character arrays. In other words, for these first two parameters, the prototype you show expects them to have been declared as char jobz[] = "Vectors" and char uplo[] = "Upper". What seems more problematic to me is that the LAPACK dsyev function (according to the docs in the link I show, and elsewhere) is expecting a single constant for jobz and uplo, 'V' and 'U', respectively.[/code]

6. Jun 7, 2015

### kroni

I don't know for your problem but please, test fin.isopen() before reading it.
If the file doesn't exist you will have a hard to find segmentation fault.

7. Jun 7, 2015

### D H

Staff Emeritus
You shouldn't be declaring the functions in the lapack library. You should instead be using a header file that comes with the library. If that header file was written for use in C but not C++ (i.e., it doesn't wrap function declarations within an extern "C" block, you can use
Code (Text):

extern "C" {
}

It was not spurious.

Consider the following:
Code (Text):

int foo () { return 42; }
int foo (int num) { return num + 42; }
double foo (double num1, int num2=42) { return num1 + num2; }
The above code is perfectly legal C++ code. C++ has overloading. C doesn't; the above is illegal in C. Actually, it's worse than illegal in C; it falls in that terrible category of "illegal" called "undefined behavior". The compiler/linker is nice if it does detect that their are multiple definitions of foo. It doesn't have to.

This possibility of overloading in C++ (but not in C) is the reason you absolutely need to use extern "C" to call a C function from C++ code. C++ compilers mangle function names so as to distinguish foo() from foo(int) and foo(double). For example, the C++ function double foo(double num1, int num2) becomes __Z3foodi on my computer with my compiler. When compiled as a C function, the same function becomes _foo with my compiler. These different linkage rules for C versus C++ means you need to tell the compiler that the C functions you are calling are indeed C functions, not C++ functions.

In this case, those warnings are benign. Those warnings do however need to be there. You are (potentially) invoking undefined behavior. What if dysev changes the contents of that string? That's undefined behavior. The function dysev doesn't do that, but the prototype says that it might well do exactly that. A good compiler will warn you when you supply a const array to a function that takes a non-const array as an argument.