seg fault when calling virtual function of struct - c++

I have a C++ code below which create an array of pointers to a struct
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#define WATCH(x) std::cout << #x << ": " << x << std::endl;
typedef struct
{
double thickness;
char name[80];
virtual double getDensity() const {return 0.1;}
} mat_prop_t;
struct mat_el_prop : public mat_prop_t
{
double density;
double young;
double poisson;
virtual double getDensity() const {return density;}
};
int main(int argc, char** argv)
{
mat_prop_t** mat_prop;
mat_prop = (mat_prop_t**) calloc(1, sizeof(mat_prop_t*));
mat_prop[0] = (mat_prop_t*) calloc(1, sizeof(mat_el_prop));
mat_el_prop* mat1 = (mat_el_prop*) mat_prop[0];
mat1->density = 2.038735;
mat1->young = 2.0;
mat1->poisson = 0.3;
mat1->thickness = 1.0;
WATCH(mat1->density)
WATCH(mat1->getDensity())
free(mat_prop[0]);
free(mat_prop);
return 0;
}
I think the construct is correct, but it gives a seg fault error at line
WATCH(mat1->getDensity())
However, when the virtual keyword is removed, the code runs fine. Could anybody help to explain to me why?

calloc() can only be used to allocate space for primitive types and POD structures. Since your struct has a virtual function, it's not POD, so you need to use new to ensure that the vtable is created properly.
mat_prop_t **mat_prop = new mat_prop_t*[1];
mat_prop[0] = new mat_el_prop;
mat_el_prop *mat1 = mat_prop[0];
You could technically use calloc() for mat_prop, since it's an array of pointers. But in C++ you should generally use new, not the C memory allocation functions.

Related

Process Exit: value 3221225477

When I am adding
local_w_p_n->wp_val_p = rx_pbuf;
local_w_p_n->wp_val_n = rx_netif;
in rx_local_p_n function to the program code, the code is compiled but running in Process Exit: value 3221225477. Does anyone know why and how to fix it?
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
struct pbuf{
int a;
int b;
};
struct netif{
int c;
int d;
};
struct wrapper_p_n{ // wrapper for pbuf- and netif-struct pointer
struct pbuf *wp_val_p;
struct netif *wp_val_n;
};
void rx_local_p_n(struct pbuf *rx_pbuf, struct netif *rx_netif)
{
// wrap the received pointer
struct wrapper_p_n *local_w_p_n;
local_w_p_n->wp_val_p = rx_pbuf;
local_w_p_n->wp_val_n = rx_netif;
printf("rx_local_p_n\n");
//Passing *local_w_p_n pointer to another function
//check_value(local_w_p_n);
}
int main(int argc, char** argv) {
// give values to local_pbuf and netif
struct pbuf local_pbuf;
local_pbuf.a = 1;
local_pbuf.b = 2;
struct netif local_netif;
local_netif.c = 3;
local_netif.d = 4;
//passing pbuf- and netif-stuct to function
rx_local_p_n(&local_pbuf, &local_netif);
printf("return\n");
return 0;
}
struct wrapper_p_n *local_w_p_n;
local_w_p_n->wp_val_p = rx_pbuf;
local_w_p_n->wp_val_n = rx_netif;
local_w_p_n is an uninitalised pointer, and dereferencing it is liable to cause your program to crash.
Judging by the commented out code, what you are really looking for is this
struct wrapper_p_n local_w_p_n;
local_w_p_n.wp_val_p = rx_pbuf;
local_w_p_n.wp_val_n = rx_netif;
//Passing pointer to local_w_p_n to another function
check_value(&local_w_p_n);
Instead of declaring a pointer, the code above declares a regular variable, and then uses the address-of operator & to obtain a pointer to that variable.
In fact you wrote exactly the same code in main, so not sure why you tried something different here.

Virtual function with unkown parameter vector type

I am trying to build an optimization library in C++ for parameters optimization.
The problem and the parameters type may vary, e.g. if the problem is to minimize the Ackley Function, then we have a vector<double> of size 2 (index 0 for the x, and index 1 for the y). However, we may have problems where the parameters are integers, or even strings.
Many algorithm exist for this type of optimization, like Genetic Algorithm, Differential Evolution, etc. In most of them, once we modify the parameters based on their optimization strategy, we have to call an evaluation function that receives the parameters, and given a objective function, will return a value (fitness).
My question is how could I implement an abstract class Problem in C++ such that it contains an virtual double evaluate function in which receives as reference a vector of the generic type of the related problem? For example, user's problem should inherit Problem and he needs to specify a type T, in this case, the evaluation function should be like virtual double evaluate(const vector<T> &parameters){}.
If the strategy which I mentioned above is not feasible for C++. Please, suggest alternatives strategies.
Based on #Quentin comment and your details I would say that you could first declare Problem as a class template
#include <vector>
#include <typeinfo>
#include <iostream>
using namespace std;
template<class T>
class Problem
{
public:
Problem() {
if(typeid(T) == typeid(double)){
cout << "The problem is of type double" << endl;
}
}
virtual double evaluate(const vector<T> &decisionVariables) = 0;
};
Then you can inherit from it and override the evaluate function based on your needs. Since you mentioned Ackley Function, I implemented an AckleyFunction which inherits from Problem with type double
#include "problem.h"
#include "math.h"
using namespace std;
class AckleyFunction : public Problem<double>
{
public:
AckleyFunction() {}
double evaluate(const vector<double> &decisionVariables) override {
const double x = decisionVariables[0];
const double y = decisionVariables[1];
return -20 * exp(-0.2 * sqrt(0.5 * (pow(x, 2) + pow(y, 2)))) - exp(0.5 * (cos(2 * M_PI * x) + cos(2 * M_PI * y))) + exp(1) + 20;
}
};
The global minimum for the Ackley function is x = 0, and y = 0. You can see that bellow in the main.cpp
#include <ackleyfunction.h>
#include <memory>
using namespace std;
int main(int argc, char *argv[])
{
shared_ptr<Problem<double>> prob(new AckleyFunction());
vector<double> decisionVariables = {5.1, 3.3};
cout << "Value at coordinates (5.1, 3.3): " << prob->evaluate(decisionVariables) << endl;
decisionVariables = {0., 0.};
cout << "Value at coordinates (0.0, 0.0): " << prob->evaluate(decisionVariables) << endl;
}
Output:
The problem is of type double
Value at coordinates (5.1, 3.3): 12.9631
Value at coordinates (0.0, 0.0): 0
Would something like this do?
#include <memory>
#include <iostream>
#include <vector>
class Problem {
public:
virtual double evaluate() = 0;
};
class MyProblem : public Problem {
public:
MyProblem(const std::vector<float>& parameters) : mParameters(parameters) {}
double evaluate() override {
// Do evaluation based on mParameters
return 47.11;
}
private:
const std::vector<float>& mParameters;
};
int main() {
std::vector<float> v = {1.0f, 2.0f};
std::unique_ptr<Problem> p{new MyProblem(v)};
std::cout << p->evaluate() << '\n'; // Calls MyProblem::evaluate()
return 0;
}

What is this error for in my C++ program?

I wrote the below program to set a value (here it's 3) to some location at memory that is pointed by a pointer named p using a function named f() and print it in the main:
#include <iostream>
using namespace std;
void f(float* q)
{
q=new float;
*q=3;
}
int main()
{
float *p= nullptr;
f(p);
cout<<*p;
return 0;
}
But when I want to compile it, I receive this compile time error :
ap1019#sharifvm:~$ g++ myt.cpp
myt.cpp: In function âint main()â:
myt.cpp:12:11: error: ânullptrâ was not declared in this scope
float *p=nullptr;
^
ap1019#sharifvm:~$
What's wrong?
It seems that pointer literal nullptr is not supported by your compiler.
You may use null pointer constant instead. For example
float *p = 0;
But in any case your program is wrong. It has a memory leak because you store the address of the allocated memory in a local variable of function f that will be destroyed after exiting the function.
The program could look the following way
#include <iostream>
using namespace std;
void f( float **q)
{
*q = new float;
**q = 3;
}
int main()
{
float *p = 0;
f( &p );
cout << *p;
delete p;
return 0;
}
Or you could use reference to the pointer. For example
#include <iostream>
using namespace std;
void f( float * &q)
{
q = new float;
*q = 3;
}
int main()
{
float *p = 0;
f( p );
cout << *p;
delete p;
return 0;
}
nullptr is only supported from gcc-4.6 or later.
You can easily workaround that with a const void *nullptr=(void*)0;, but to avoid later problems with a gcc upgrade, I suggest to
upgrade your gcc (4.6 is quite old)
or don't use it.
It is only syntactic sugar, you don't need that.
The word null is not reserved by the C++ standard.
Use NULL instead.

Array of templated structs

I have structs templated by int derived from a Base struct.
struct Base { int i; double d; };
template< int N > struct Derv : base { static const int mN = N; };
I need to make an array of Derv< N > where N can vary for each struct in that array. I know C/C++ does not allow arrays of objects of different types, but is there a way around this? I was thinking of separating the type information somehow (hints like pointers to Base struct or usage of union spring to my mind, but with all of these I don't know how to store the type information of each array element for usage DURING COMPILE TIME). As you can see, the memory pattern of each Derv< N > is the same.
I need to access the type of each array element for template specialization later in my code. The general aim of this all is to have a compile-time dispatch mechanism without the need to do a runtime "type switch" somewhere in the code.
It is most certainly impossible. If you did
int i;
std::cin >> i;
some_magic_array X[size];
Then what is the type of X[i]? Oh, wait, you can't possibly know. It's nothing C++ specific, it's fundamentally impossible. That's why no some_magic_array will ever exist that permits this.
Unless you effectively use a std::tuple and guarantee that i is constexpr. Then you absolutely can do this with std::get<i>(tup);.
I guess you can use ptr = dynamic_cast<Type>(element); .. ptr will equal to NULL if it's the wrong type.
For example:
#include <map>
#include <cmath>
#include <vector>
#include <string>
#include <cstdlib>
#include <fstream>
#include <sstream>
#include <iostream>
using namespace std;
struct Base { int i; double d; Base(){}; virtual ~Base(){};};
template< int N > struct Derv : public Base { static const int mN = N; ~Derv(){}; };
int main(int argc, char **argv){
Base* arr[2];
arr[0] = new Derv<10>;
arr[1] = new Derv<5>;
Derv<10> *ptr = dynamic_cast<Derv<10>* >(arr[0]);
Derv<5> *ptr2 = dynamic_cast<Derv<5>* >(arr[0]);
cout << ptr << endl << ptr2 << endl;
return 0;
}
// That should print
0x9571008 //ptr to object will differ every time.
0 // Null because of wrong type.
But you'll need to define virtual destructor in your struct for this to work, and/or a virtual function.

"Warning: Can't find linker symbol for virtual table for value XXX value" using GCC and GDB (CodeBlocks)

I'm getting a runtime error ("memory can't be written") that, after inspection through the debugger, leads to the warning in the tittle.
The headers are the following:
componente.h:
#ifndef COMPONENTE_H
#define COMPONENTE_H
using namespace std;
class componente
{
int num_piezas;
int codigo;
char* proovedor;
public:
componente();
componente(int a, int b, const char* c);
virtual ~componente();
virtual void print();
};
#endif // COMPONENTE_H
complement.h implementation
#include "Componente.h"
#include <string.h>
#include <iostream>
componente::componente()
{
num_piezas = 0;
codigo = 0;
strcpy(proovedor, "");
//ctor
}
componente::componente(int a = 0, int b = 0, const char* c = "")
{
num_piezas = a;
codigo = b;
strcpy(proovedor, "");
}
componente::~componente()
{
delete proovedor;//dtor
}
void componente::print()
{
cout << "Proovedor: " << proovedor << endl;
cout << "Piezas: " << num_piezas << endl;
cout << "Codigo: " << codigo << endl;
}
teclado.h
#ifndef TECLADO_H
#define TECLADO_H
#include "Componente.h"
class teclado : public componente
{
int teclas;
public:
teclado();
teclado(int a, int b, int c, char* d);
virtual ~teclado();
void print();
};
#endif // TECLADO_H
teclado.h implementation
#include "teclado.h"
#include <iostream>
teclado::teclado() : componente()
{
teclas = 0;//ctor
}
teclado::~teclado()
{
teclas = 0;//dtor
}
teclado::teclado(int a = 0, int b = 0, int c = 0, char* d = "") : componente(a,b,d)
{
teclas = c;
}
void teclado::print()
{
cout << "Teclas: " << teclas << endl;
}
The main method where I get the runtime error is the following:
#include <iostream>
#include "teclado.h"
using namespace std;
int main()
{
componente a; // here I have the breakpoint where I check this warning
a.print();
return 0;
}
BUT, if instead of creating an "componente" object, I create a "teclado" object, I don't get the runtime error. I STILL get the warning during debugging, but the program behaves as expected:
#include <iostream>
#include "teclado.h"
using namespace std;
int main()
{
teclado a;
a.print();
return 0;
}
This returns "Teclas = 0" plus the "Press any key..." thing.
Do you have any idea why the linker is having troube with this? It doesn't show up when I invoke the virtual function, but before, during construction.
Two errors that I can see:
strcpy(proovedor, ""); // No memory has been allocated to `proovedor` and
// it is uninitialised.
As it is uninitialised this could be overwriting anywhere in the process memory, so could be corrupting the virtual table.
You could change this to (in both constructors):
proovedor = strdup("");
Destructor uses incorrect delete on proovedor:
delete proovedor; // should be delete[] proovedor
As this is C++ you should considering using std::string instead of char*.
If you do not change to std::string then you need to either:
Implement a copy constructor and assignment operator as the default versions are incorrect if you have a member variable that is dynamically allocated, or
Make the copy constructor and assignment operator private to make it impossible for them to be used.
Another source of this same message is that gdb can get confused by not-yet-initialized variables. (This answers the question title, but not the OP's question, since a web search led me here looking for an answer.)
Naturally, you shouldn't have uninitialized variables, but in my case gdb attempts to show function local variables even before they are declared/initialized.
Today I'm stepping through another developer's gtest case and this message was getting dumped to output every time the debugger stopped. In this case, the variable in question was declared on ~line 245, but the function started on ~line 202. Every time I stopped the debugger between these lines, I received the message.
I worked around the issue by moving the variable declaration to the top of the function.
For reference, I am testing with gdb version 7.11.1 in QtCreator 4.1.0 and I compiled with g++ version 5.4.1