I'm trying to learn about pointers and first class objects in C++. I'm sure the problem exists in my pointer assignments or calls. I was wondering if someone could help me to better understand pointers as well as using static variables/methods.
FirstClass.h
#pragma once
class FirstClassObject {
public: FirstClassObject();
FirstClassObject(int);
FirstClassObject(int, FirstClassObject);
static void next_attr();
static int attribute;
int num;
FirstClassObject *buffer;
FirstClassObject *next;
~FirstClassObject();
};
FirstClassObject.cpp
#include "FirstClass.h"
#include <stdlib.h>
#include <string>
using namespace std;
FirstClassObject::FirstClassObject(){
num = attribute;
next_attr();
};
FirstClassObject::FirstClassObject(int attr){
num = attr;
next_attr();
}
FirstClassObject::FirstClassObject(int attr, FirstClassObject object){
num = attr;
next_attr();
buffer = (FirstClassObject*) malloc(5);
memcpy(buffer,&object,1);
next = buffer;
}
void FirstClassObject::next_attr(){
attribute++;
}
FirstClassObject::~FirstClassObject(){
free(buffer);
free(next);
}
FirstClassObject_test.cpp
#include "FirstClass.h"
#include <iostream>
using namespace std;
int FirstClassObject::attribute = 0;
FirstClassObject get_next_object(FirstClassObject object){
FirstClassObject next_object;
next_object.buffer = object.next;
return next_object;
}
int main(){
FirstClassObject object;
FirstClassObject otherobject(4, object);
cout << get_next_object(otherobject).num << "these numbers should be the same " << object.num << '\n';
return 0;
}
Thanks in advance.
First and foremost, this is wrong:
buffer = (FirstClassObject*) malloc(5);
memcpy(buffer,&object,1);
malloc() is not the same as new[].
Your FirstClassObject type is a non-POD type since it has a non-trivial destructor. This means you cannot properly construct it using malloc(). All malloc() does is allocate memory, and that's it. You need to actually construct a FirstClassObject object, and to do that using dynamically, you use new[ ].
Secondly, malloc() requires the number of bytes to allocate. What is sizeof(FirstClassObject)? I bet it isn't 5 (the argument you gave to malloc()). But the main point is that even if you gave malloc() the correct number of bytes, you aren't properly constructing your objects by using it.
Third, because FirstClassObject is non-POD, usage of memcpy() is also not good. In short, memcpy() does not copy objects. To copy an object, you invoke the copy constructor.
It looks like you're reading C language books and/or reading C language resources, not C++ books and resources. If you are, put down the C for a bit and learn C++ from the proper sources. If you attempt to mix C with C++ (without the proper experience), you wind up with issues such as your example.
First:
buffer = (FirstClassObject*) malloc(5)
This allocates a buffer of size 5, not 5 FirstClassObject. To do this, you need to do something like:
buffer = (FirstClassObject*) malloc(5*sizeof(FirstClassObject));
Second:
memcpy(buffer,&object,1);
This copies only 1 byte out of your object struct. Not a complete object. Here, sizeof is your friend as well although it is dangerous as receiving buffer is not a fully constructed object.
Then this line:
next_object.buffer = object.next;
would do member to member copy(providing it compiled as you are trying to affect an object to a pointer) effectively writing pass the boundary of your previously under-allocated buffer giving you the assert.
Related
I'm having a data abort exception in my code. It is very likely I am doing a very bad operation with chars. This code seems to work, but I wonder if it is actually invalid. The question is, what happens if you copy the data of one struct to another with char arrays involved. How is the data copied?
I have two functions, one which will purposefully leak, because I want to also know what happens if the struct created with new lives on purposefully, but the struct whose data it copied goes out of scope.
// Example program
#include <iostream>
#include <string>
#include "string.h"
typedef struct {
char name[12];
char stupid[12];
int hello;
} tFile;
void CopyFileAndDelete(tFile *file1){
tFile *file2 = new tFile;
*file2 = *file1;
std::cout << file2->name << std::endl;
delete file2;
}
void CopyFileAndLeak(tFile *file1){
tFile *file2 = new tFile;
*file2 = *file1;
std::cout << file2->name << std::endl;
}
int main()
{
tFile file1;
memset(&file1, 0, sizeof file1);
file1.hello = 22;
snprintf(file1.name, 12, "%s", "hellogoodfriendhwoareyou");
snprintf(file1.stupid, 12, "%s", "greate");
CopyFileAndDelete(&file1);
CopyFileAndLeak(&file1);
}
Other than this code being generally unsafe and more C than C++, it's correct (other than the leak.) There is no way this can produce an exception (unless new throws due to memory allocation failure.)
Arrays inside structs will be copied as you'd expect. The compiler will generally do a memcpy() to copy them (or a special memcpy-like built-in to optimize the copy operation.)
This isn't code you should write though. Use std::string instead. Don't use new and delete, use value types instead. If you really need to allocate, use unique_ptr or shared_ptr to do it.
Don't write code like this in C++ :-)
I am having a problem with assigning new values to a dynamic int array that is a data member variable of the class IntersectionFlowRate(). I can initialize and print the values of the array inside the constructor. However, when I exit the constructor to the another class and then later call a function within the IntersectionFlowRate() class passing in variables to overwrite the initial values of the data member it will segmentation fault. I have debugged to find that overwriting the array is causing the seg fault. And that even attempting to access the dynamic array within one of its functions will seg fault.
My question is how can I edit the values of a dynamic int array member variable from within one of its functions i.e setArrayElement(int index, int x).
Here is some of my code. Sorry if I am unclear or missing something ridiculous. I have been stuck on this for hours.
#ifndef INTERSECTIONFLOWRATE_H
#define INTERSECTIONFLOWRATE_H
class IntersectionFlowRate
{
public:
IntersectionFlowRate();
~IntersectionFlowRate();
void setFlowCycle(int index, int flow);
private:
int* m_flowRateMotorCycle;
};
#endif
in the .h file ^
#include "IntersectionFlowRate.h"
#include <cstdlib>
#include <iostream>
#include <new>
using namespace std;
IntersectionFlowRate::IntersectionFlowRate()
{
const int SIZE = 4; //Constant for m_flowRates[] size
//DYNAMIC MEMORY DELETE LATER
m_flowRateMotorCycle = new int[SIZE];
for(int i = 0; i < SIZE; i++){
m_flowRateMotorCycle[i] = 0;
cout << m_flowRateMotorCycle[i] << endl;
cout << "WE GOT HERE" << endl;
}
}
void IntersectionFlowRate::setFlowCycle(int index, int flow){
cout << "INDEX: " << index << endl;
cout << "FLOW: " << flow << endl;
m_flowRateMotorCycle[index] = flow; //seg fault is here
}
I have another class that creates a pointer to a IntersectionFlowRate() object and then calls its setFlowCycle function passing in two VALID ints. With the debugging I was able pass 0 and 3 to the function setFlowCycle(0, 3) just fine and output those variables within the function.
#ifndef TRAFFICSIM_H
#define TRAFFICSIM_H
#include "IntersectionFlowRate.h"
using namespace std;
class TrafficSim
{
public:
TrafficSim(); //Default Constructor
TrafficSim(const char* file); //Constructor
~TrafficSim(); //Destructor
private:
IntersectionFlowRate* m_flowRate;
};
#endif
#include "TrafficSim.h"
#include "IntersectionFlowRate.h"
#include <iostream>
#include <string>
#include <fstream>
#include <cstdlib>
using namespace std;
TrafficSim::TrafficSim()
{
IntersectionFlowRate* m_flowRate = new IntersectionFlowRate();
m_flowRate->setFlowCycle(0, 3);
}
I replicated the error with this code. If no one else can I am completely unsure of what is possibly wrong anymore.
You are setting a local variable called m_flowRate, not the member variable m_flowRate of your TrafficSim class:
Instead of this:
TrafficSim::TrafficSim()
{
IntersectionFlowRate* m_flowRate = new IntersectionFlowRate();
m_flowRate->setFlowCycle(0, 3);
}
It should be this:
TrafficSim::TrafficSim()
{
m_flowRate = new IntersectionFlowRate();
m_flowRate->setFlowCycle(0, 3);
}
But overall, it not need be a pointer. It could be an object member within your class. That would cut down on the pointer usage a bit:
class TrafficSim
{
public:
TrafficSim(); //Default Constructor
TrafficSim(const char* file); //Constructor
private:
IntersectionFlowRate m_flowRate;
};
Then:
TrafficSim::TrafficSim()
{
m_flowRate.setFlowCycle(0, 3);
}
As to your question as to how to incorporate usage of std::vector in your class, here is a code sample of the IntersectionFlowRate class, rewritten using vector:
Vector sample
Also, another source of problems is that your classes fail to follow the Rule of 3 when you have pointers to dynamically allocated memory in your class.
Using std::vector takes care of this automatically, but if you insist on using pointers, you need to adhere to the directions at the link posted.
Yes, use a std::vector, it is much simpler, and it is a template so it also pretty fast and works any type (best for primitive types or pointers to objects) , and it also has boundary checking and other useful things.
If you need fast array-like access then you could use std::map which associates a key with a value, like so
std::map<UINT, YourClass*> m_mapIDs_to_YourClass;
When you first start using stl containers they might seem a little strange, but after a short while you cannot do without them, luckily they have been part of the C++ standard for some time now.
Boundary check for both these containers can be done by comparing your iterator to mapYourMap.end(), if they are equal you have passed the last element and trying to access data through the iterator will cause an exception.
Example for std::vector (if vecInt is a vector< int >):
vector<int>::iterator it = vecInt.begind();
if (it == vecInt.end()) return; // vector is empty
do { // runs through elememts until out of bound, useful for searching
i++
while (it != vecInt.end());
Problem
I am currently working on a plugin-library, where one should be able to not only import C-Linkage symbols, but all imported things.
Thus far it works, though the problem is, that gcc screws member-function calls up.
If I export the following:
static member_function(Class* c)
{ c->method();}
it works fine an I can access the class-members. But if I do the following:
void (Class ::*p)() = import("Class::method");
(x.*p)();
i get the right pointer and also am able to call the function and the passed arguments, but the this pointer is pointing into nirvana. I think gcc is taking it from the wrong position of the stack or something like that.
It works just fine with MSVC.
I am using mingw-w64 5.1.
Does anyone have an idea what the error could be?
Simple example:
plugin.cpp
#include <iostream>
namespace space {
class __declspec(dllexport) SomeExportThingy
{
int i = 42;
public:
virtual void __declspec(dllexport) Method(int*) const
{
using namespace std;
cout << "Calling Method" << endl;
cout << pi << endl;
cout << *pi << endl;
cout << this << endl;
cout << this->i << endl;
}
}
}
loader.cpp
namespace space {
class SomeExportThingy
{
///dummy to have some data in the address
int dummy[20];
};
int main()
{
auto h = LoadLibrary("plugin.dll");
auto p = GetProcAddress(h, "_ZNK5space16SomeExportThingy6MethodEPi");
typedef void (space::SomeExportThingy::*mptr)(int*) const;
///used because posix passed void*
auto fp = *reinterpret_cast<mptr*>(&p);
space::SomeExportThingy st;
int value = 22;
cout << "ValueLoc: " << &value << endl;
cout << "StLoc: " << &st << endl;
(st.*fp)(&value);
}
Results
Now what happens is, that the function is called and the pointer to pi is passed correctly. However, the this pointer is completly screwed up.
Again: it works with MSVC, which get's the this pointer correctly, but gcc get's this wrong.
I have no idea why this happens, and removing the virtual from the method doesn't change that either.
I have no idea what causes this, so maybe someone has an idea what the ABI is doing here.
Here are the pointers I am getting:
0x00400000 == GetModuleHandleA(NULL)
0x61840000 == GetModuleHandleA("plugin.dll")
0x0029fcc4 == _&st
0x00ddcd60 == this
I wasn't able to find any relation between the values
This is not going to work with GCC:
typedef void (space::SomeExportThingy::*mptr)(int*) const;
///used because posix passed void*
auto fp = *reinterpret_cast<mptr*>(&p);
The representation of a pointer-to-member is twice the size of a normal function pointer (or a void*) so you are reading two words from a memory location that only contains one word. The second word (which tells the compiler how to adjust the this pointer for the call) is garbage, it is just whatever happens to be after p on the stack.
See https://gcc.gnu.org/onlinedocs/gcc/Bound-member-functions.html:
In C++, pointer to member functions (PMFs) are implemented using a wide pointer of sorts to handle all the possible call mechanisms; the PMF needs to store information about how to adjust the ‘this’ pointer,
p is a void* so it's a memory location on the stack that occupies sizeof(void*) bytes.
&p is a pointer to that memory location.
reinterpret_cast<mptr*>(&p) is a pointer to 2*sizeof(void*) bytes at the same address.
*reinterpret_cast<mptr*>(&p) reads 2*sizeof(void*) bytes from a memory location that is only sizeof(void*) bytes in size.
Bad things happen.
For linux, the functions for dynamic function loading are: dlopen(), dlsym(), and dlclose(). Please reference: dlopen() man page.
Consider that C++ method names are 'mangled' and and they have an invisible '*this' parameter passed before all the others. Together both issues makes trying to directly access C++ objects not trivial when using dynamic linking.
The easiest solution I've found is to use 'C' function(s) that expose access to the C++ object instance.
Secondly, memory management of C++ objects is not trivial when the code to instantiate is within an .so library object, though the referencing code is from the user's app.
For the long answer as to why avoiding Pointer to C++ Member Methods is difficult, please reference: ISO CPP Reference, Pointers to Methods.
/** File: MyClass.h **/
// Explicitly ensure 'MyClassLoaderFunc' is NOT name mangled.
extern 'C' MyClass* MyClassLoaderFunc(p1, p2 ,p3, etc );
extern 'C' MyClass* MyClassDestroyerFunc(MyClass* p);
// Create function pointer typedef named 'LoaderFuncPtr'
typedef MyClass*(MyClassLoaderFunc* LoaderFuncPtr)(p1,p2,p3,etc);
// Define MyClass
class MyClass
{
/** methods & members for the class go here **/
char dummy[25];
int method( const char *data);
};
/** File: MyClass.cpp **/
#include "MyClass.h"
MyClass* MyLoaderFunc(p1, p2 ,p3, etc) {
MyClass* newInstance = new MyClass::CreateInstance( p1, p2, p3, etc);
/** Do something with newInstance **/
return newInstance;
}
MyClass::method(const char* data)
{
}
/** File: MyProgram.cpp **/
#include "MyClass.h"
main()
{
// Dynamically load in the library containing the object's code.
void *myClassLibrary = dlopen("path/to/MyClass.so",RTLD_LOCAL);
// Dynamically resolve the unmangled 'C' function name that
// provides the bootstrap access to the MyClass*
LoaderFuncPtr loaderPtr = dlsym(myClassLibrary,"MyClassLoaderFunc");
DestroyFuncPtr destroyerPtr = dlsym(myClassLibrary,"MyClassDestroyerFunc");
// Use dynamic function to retrieve an instance of MyClass.
MyClass* myClassPtr = loadPtr(p1,p2,p3,etc);
// Do something with MyClass
myClassPtr->method();
// Cleanup of object should happen within original .cpp file
destroyPtr(myClassPtr);
myClassPtr = NULL;
// Release resources
dlclose(myClassLibrary);
return 0;
}
Hope this helps..
I also suggest a factory paradigm as an more robust solution, that I'll leave to the reader to explore.
As Jonathan pointed out, pointer-to-members are bigger than normal function pointers.
The simplest solution is to reserve and initialize the extra space.
typedef void (space::SomeExportThingy::*mptr)(int*) const;
union {
mptr fp;
struct {
FARPROC function;
size_t offset;
};
} combFp;
combFp.function = p;
combFp.offset = 0;
auto fp = combFp.fp;
I was just messing around with passing pointers to functions to wrap my head around how it works and I came across some behavior that was unexpected. I have the following code:
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <cmath>
#include <iomanip>
using namespace std;
struct t
{
string x;
string y;
};
void foo(t*);
int main()
{
t* ts = new t[2];
ts[0].x = "t1.x";
ts[0].y = "t1.y";
ts[1].x = "t2.x";
ts[1].y = "t2.y";
foo(ts);
cout << ts[0].x << endl;
}
void foo(t* s)
{
delete[] s;
s = new t[2];
s[0].x = "FOO.X";
s[1].y = "FOO.Y";
}
The output here, interestingly enough, is "FOO.X". I expected that since inside of foo, s is a copy of the pointer ts that when I delete[] s I effectively delete[] ts as they both point to the same address. Then s = new t[2]; should have no effect on ts. After foo returns, I should no longer have access to s or the array it points to and ts should point to who knows where. Am I missing somehthing?
Note: This is just a test project that I made where I constantly write and erase blocks of code to test different concepts. All the includes and using namespace std is for ease of use, and it is NOT code that I am writing for any sort of practical use, purely educational. Also, I am using MS VS 2013.
Try changing your foo() like this and see the result:
void foo(t* s)
{
delete[] s;
// Additional memory allocation
t* u = new t[2];
s = new t[2];
s[0].x = "FOO.X";
s[1].y = "FOO.Y";
}
By adding another memory allocation, I moved s to another location in the memory, which is not anymore overlapping with ts. Otherwise, s was simply allocated at the same location where ts previously resided.
As pointed out in the comments, you are observing an undefined behavior, which you should by no means rely on. The example above illustrates that pretty well.
I have a class I’d like to be able to set a flag in that says if it is heap allocated so it can properly clean up after itself and not try to delete itself if it’s on the stack. The problem is...I can’t seem to override both new and the constructors at the same time. So it goes from my new overload that sets the isHeapAllocated flag and then into my constructor which resets the flag.
void* String8::operator new(size_t size)
{
String8* string = (String8*)malloc(size);
if(string == null)
Exception("allocation fail : no free memory");
string->isHeapAllocated = true;
return string;
}
String8::String8()
{
isHeapAllocated = false;
}
So new String8() sets the isHeapAllocated flag and then resets it to false. Is there any way to do this?
It will not work as intended:
The new operator return unitialized memory to be given to the constructor.
You -correctly- do String8* string = (String8*)malloc(size);, but *string, at this stage is not yet a String8 object: it is just the memory bulk that will contain it.
So string->isHeapAllocated = true; in fact sets a flag inside a not yet constructed object (that's UB).
Admitting this will not compromise the OS process, so that the program will not crash (you write memory that belongs already to you, after all ...), when you will later do something like String8* ptr = new String8;, after new returns, the String8::String8 constructor is called, and the member will be set back to "false" independently on what you did in the new operator overload.
The idiomatic way to manage C++ objects is let who allocate to be responsible to deallocate.
(and if "who" it is the stack, it just do that by definition).
This is a bad idea, but here’s a way to do it that doesn’t invoke undefined behaviour.
#include <iostream>
#include <memory>
#include <set>
using namespace std;
class C {
public:
void* operator new(size_t size) {
C* c = static_cast<C*>(::operator new(size));
heap_instances.insert(c);
return c;
}
C() : heap_allocated(heap_instances.find(this) != heap_instances.end()) {}
const bool heap_allocated;
private:
static set<const C*> heap_instances;
};
set<const C*> C::heap_instances;
int main(int argc, char** argv) {
cout << boolalpha;
C stack;
cout << stack.heap_allocated << '\n'; // false
C* heap_nozero = new C;
cout << heap_nozero->heap_allocated << '\n'; // true
delete heap_nozero;
C* heap_zero = new C();
cout << heap_zero->heap_allocated << '\n'; // true
delete heap_zero;
}
You can remove pointers from heap_instances when you’re done with them, of course, and use a more suitable container if you’re running in a multithreaded environment. But again, I wouldn’t recommend that you actually do this—deciding behaviour based on allocation is not something an object ought to do.
The only legitimate reason I can think of for this is to enable delete this. While that’s safe if you’re careful not to access members after the object’s suicide, it’s usually saner to let objects manage the lifetimes of other objects.
Note that the construtor gets called if it is allocated on the stack or the heap and there is no way for the object to detect if it was allocated on the stack or in the heap.
To create an object at the stack you don't use any memory allocation functions like this
String8 myString;
To create it on the heap you do
String8 *myString = new String8();
note that you do have to do the cleanup manually after not using the object anymore.
For the use of Heap objects bound to stack scope you can check out the RAII principle which is used intensly by c++ programs (see here for a better explaination of the difference of heap allocation and stack allocation).
Not sure why you need this, really. It's caller's responsibility to call delete if needed and your class's destructor should not be different whether it's called on the object on stack or on the heap... But, maybe, you are doing some special purpose class... Here is my quick take on it.
EDIT: You should also, probably, add custom delete operator to your class, unless you know that global delete calls a deallocation function that matches the allocation function you use in your custom new operator.
#include <cstdlib>
#include <iostream>
namespace so
{
class _test_
{
private:
static bool flag_allocation_heap;
bool flag_heap;
public:
_test_()
: flag_heap( flag_allocation_heap )
{
flag_allocation_heap = 0;
std::cout << flag_heap << std::endl;
}
void * operator new( std::size_t _size )
{
_test_ * test_ = static_cast< _test_ * >( std::malloc( _size ) );
flag_allocation_heap = 1;
return ( test_ );
}
};
bool _test_::flag_allocation_heap = 0;
} // namespace so
int main()
{
so::_test_ test_stack_;
so::_test_ * test_memory_ = new so::_test_;
delete test_memory_;
return( 0 );
}
Output:
0
1