I have made a program that contains the following function in C:
void *e_malloc(size_t size)
{
void *m = malloc(size);
if (!m)
{
printf("Out of memory, fatal error.");
abort();
}
return m;
}
I am using this as an error free malloc that exits the program when out of memory. The thing is, that when I compile the code in linux with g++, I get an error because it says that it needs to be casted, and as you can see I always return a void pointer cause that's what malloc returns (gcc of course compiles fine). Is there a way I could modify this function to make it work on both compilers ? Do I just have to cast it every time ? Are there other options to make what I am trying to do ?
Also, when I use Cmake (through Clion IDE) the code compiles just fine with "-std=C++11". Why is that ?
You could make it easier to use with macros:
#define e_new(type) ((type*)malloc(sizeof(type)))
#define e_new_array(type, count) ((type*)malloc((count)*sizeof(type)))
example usage:
graph_t *g = e_new(graph_t);
graph_t *ten_gs = e_new_array(graph_t, 10);
Note that this is not specific to your e_malloc - malloc itself has the same problem in C++.
As the compiler error clearly states, the error is in your calling code, not in your e_malloc.
You probably have something like this:
graph_t *g;
g = e_malloc(sizeof(graph_t));
The error is the type conversion between the void * returned by e_malloc and the expected graph_t*. Regular malloc shows the same behavior. You need to do the typecast explicitly:
g = (graph_t*)e_malloc(sizeof(graph_t));
You should not be using this construct in C++ at all. In C++, you need to use new, not malloc - and new already throws an exception (by default). Problem solved.
Related
I have been working on this simply hobbyist OS, and I have decided to add some C++ support. Here is the simple script I wrote. When I compile it, I get this message:
cp.o: In function `caller':
test.cpp:(.text+0x3a): undefined reference to `__stack_chk_fail'
Here is the script:
class CPP {
public:
int a;
void test(void);
};
void CPP::test(void) {
// Code here
}
int caller() {
CPP caller;
caller.test();
return CPP.a;
}
Try it like this.
class CPP {
public:
int a;
void test(void);
};
void CPP::test(void) {
CPP::a = 4;
}
int caller() {
CPP caller;
caller.test();
return caller.a;
}
int main(){
int called = caller();
std::cout << called << std::endl;
return 0;
}
It seems to me that the linker you are using can't find the library containing a security function crashing the program upon detecting stack smashing. (It may be that the compiler doesn't include the function declaration for some reason? I am not familiar who actually defies this specific function.) Try compiling with -fno-stack-protector or equivalent.
What is the compiler used? A workaround might be defining the function as something like exit(1); or similar. That would produce the intended effect yet fix the problem for now.
I created a test program to show how this actually plays out. Test program:
int main(){
int a[50]; // To have the compiler manage the stack
return 0;
}
With only -O0 as the flag ghidra decompiles this to:
undefined8 main(void){
long in_FS_OFFSET;
if (*(long *)(in_FS_OFFSET + 0x28) != *(long *)(in_FS_OFFSET + 0x28)) {
/* WARNING: Subroutine does not return */
__stack_chk_fail();
}
return 0;
}
With -fno-stack-protector:
undefined8 main(void){
return 0;
}
The array was thrown out by ghidra in decompilation, but we see that the stack protection is missing if you use the flag. There are also some messed up parts of this in ghidra (e.g. int->undefined8), but this is standard in decompilation.
Consequences of using the flag
Compiling without stack protection is not good per se, but it shouldn't affect you in much. If you write some code (that the compiler shouts you about) you can create a buffer overflowable program, which should not be that big of an issue in my optinion.
Alternative
Alternatively have a look at this. They are talking about embedded systems, but the topic seems appropriate.
Why is the code there
Look up stack smashing, but to my knowledge I will try to explain. When the program enters a function (main in this case) it stores the location of the next instruction in the stack.
If you write an OS you probably know what the stack is, but for completeness: The stack is just some memory onto which you can push and off which you can pop data. You always pop the last pushed thing off the stack. C++ and other languages also use the stack as a way to store local variables. The stack is at the end of memory and when you push something, the new thing will be further forward rather than back, it fills up 'backwards'.
You can initialise buffers as a local variable e.g. char[20]. If you filled the buffer without checking the length you might overfill this, and overwrite things in the stack other than the buffer. The return address of the next instruction is in the stack as well. So if we have a program like this:
int test(){
int a;
char buffer[20];
int c;
// someCode;
}
Then the stack will look something like this at someCode:
[ Unused space, c, buffer[0], buffer[1] ..., buffer[19], a, Return Address, variables of calling function ]
Now if I filled the buffer without checking the length I can overwrite a (which is a problem as I can modify how the program runs) or even the return address (which is a major flaw as I might be able to execute malicious shellcode, by injecting it into the buffer). To avoid this compilers insert a 'stack cookie' between a and the return address. If that variable is changed then the program should terminate before calling return, and that is what __stack_chk_fail() is for. It seems that it is defined in some library as well so you might not be able use this, despite technically the compiler being the one that uses this.
I'm trying to work with a C interface generated using camlidl. The library I'm working with returns an error code by allocating and filling an in/out argument char* error_message and returning it. After the function call, I check the error code for non-zero... if true, I call caml_failwith(error_message) to throw an OCaml exception using the library error message.
However, I started digging a bit, because throwing the exception looks as though it will terminate the function and never free the error message. Consider this mock code:
/* in the C stub function call... */
double _res;
int error = 0;
char* error_message = NULL;
// if this function errors, it will set error to non-zero
// and strdup something into error_message
_res = call_library_function(&error, error_message);
if (error) {
caml_failwith(error_message);
free(error_message); // NEVER CALLED?
}
/* code to copy result to an OCaml value and return */
The exception func caml_failwith(s) implementation is in runtime/fail_*.c, but it basically just calls caml_raise_with_string, which is:
CAMLparam1(tag);
value v_msg = caml_copy_string(msg);
caml_raise_with_arg(tag, v_msg);
CAMLnoreturn;
So, it copies the string to the OCaml value with caml_copy_string, and then raises the arg and no-returns. In short, error_message is lost.
...Right? What am I missing here... I could use canned strings but that makes dynamic error messages impossible. I could maybe use static char*, though it's not thread safe any more without a bunch of work. Is there any way to call caml_failwith, using a plain old dynamic char*, and not have it cause a leak?
EDIT: I thought of one solution...
char error_message_buf[100] = {'\0'};
double _res;
// ... rest of local vars and service call ...
if (error) {
strncpy(error_message_buf, error_message, 99)
free(error_message);
caml_failwith(error_message_buf);
}
... but man that's ugly. strncpy to the stack just to turn around and caml_copy_string again? Plus, it sets a hardcoded cap on error message length. Still, if it's the only way not to leak...
caml_failwith() is designed so you can call it with a constant string, which is a very common case:
caml_failwith("float_of_string");
So, you can't expect it to free its argument.
I don't personally consider this a space leak, it's just how the function is designed.
Your solution of copying the message first seems reasonable (and not particularly ugly) to me.
(This, in essence, is why I switched from C to OCaml many years ago.)
When I debug on actual devices, there is no error, but when I use the simulator, Xcode's debugger console displays the following error when running:
malloc: *** error for object 0xaaaaaaaa: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
The error always happens at the same line, which is in the constructor of another class:
Segment *segment = new Segment(0.0,0.0,3.0,1.3,10);
this->segments.push_back(segment); // Malloc error at this line
My Segment class:
class Segment {
private:
float ajc;
float frl;
std::unordered_map<int,int> jgrc;
std::vector<int> lorb;
public:
std::tuple<float,float> getMjt();
float getBuw();
….
Segment(float a, float f,float g, float lo, float u){
……
};
};
On the simulator, regardless of iOS version, the error appears. On devices, regardless of version, there is no error.
I have heard about the rule of 3, but in this case I don't think I need to apply it because the default compiler supplied code should work (unless I'm mistaken). What am I doing wrong, and how can I fix this ? Since there is no error reported on devices, should i ignore it ?
First put a NULL check to avoid the run time error. I tried a pseudo code on VS and it seemed to work. I hope your vector is similar.
Segment *segment = new Segment(0.0, 0.0, 3.0, 1.3, 10);
std::vector<Segment*> vec;
if (NULL != segment)
vec.push_back(segment);
I think there is some problem with your simulator not working fine.
The solution works, but I don't understand why. If someone with more c++ can explain it well, I will mark that as the correct answer.
The following code runs in the constructor of my class that creates the segments:
Segment *segment = new Segment(0.0,0.0,3.0,1.3,10);
this->segments.push_back(segment); // Malloc error at this line
First, I used objects instead of the pointer. Then I moved the code out of the constructor, and instead call it immediately after creating an instance of the class.
Say my class is:
class MyClass{
std::vector<Segment> segments;
}
I do :
MyClass *foo = new MyClass();
foo->createSegments();
Where:
createSegments(){
Segment segment = Segment(0.0,0.0,3.0,1.3,10);
segments.push_back(segment);
}
I'm not very experienced with C++, so I don't know why this works.I also still don't know why the original error only appeared in the simulator.
I am trying to compile a code written in C (ndpiReader.c program that comes with nDPI library, hosted here). I'm using Qt Creator and GCC compiler.
After doing some research here and here, I notice that compiling C code with C++ compiler is not the best idea. But I didn't get the answer of how to do this conversion and make this code C++ compatible.
When I try to run the code in Qt Creator I get the error bellow:
error: invalid conversion from 'void*' to 'ndpi_flow_struct*' [-fpermissive]
if((newflow->ndpi_flow = malloc_wrapper(size_flow_struct)) == NULL) {
^
If more info is needed to solve the problem please leave a comment. I'm new to C++ so detailed answers with links are so much appreciated.
Edit: here is malloc_wrapper() function's code
static void *malloc_wrapper(unsigned long size) {
current_ndpi_memory += size;
if(current_ndpi_memory > max_ndpi_memory)
max_ndpi_memory = current_ndpi_memory;
return malloc(size);
}
You're seeing this error because in c++, types should have an exact match.
As we can see, the malloc_wrapper() function returns a void * and your newflow->ndpi_flow is of type ndpi_flow_struct*. So while compiling using c++ compiler, you've to add the cast, like
if((newflow->ndpi_flow=(ndpi_flow_struct*)malloc_wrapper(size_flow_struct)) == NULL) { . . .
to force the compiler in believing that the return value of malloc_wrapper() is of type (ndpi_flow_struct*).
or even better, the static cast<> (keeping in mind the C++ aspect), like
if(( newflow->ndpi_flow =
static_cast<ndpi_flow_struct*>malloc_wrapper(size_flow_struct)) == NULL) { . . .
Related Reading: A detailed answer on C++ Casting.
Usually, we just write
if((newflow->ndpi_flow = (ndpi_flow_struct*)malloc_wrapper(size_flow_struct)) == NULL) {
I have a very simple class that looks as follows:
class CHeader
{
public:
CHeader();
~CHeader();
void SetCommand( const unsigned char cmd );
void SetFlag( const unsigned char flag );
public:
unsigned char iHeader[32];
};
void CHeader::SetCommand( const unsigned char cmd )
{
iHeader[0] = cmd;
}
void CHeader::SetFlag( const unsigned char flag )
{
iHeader[1] = flag;
}
Then, I have a method which takes a pointer to CHeader as input and looks
as follows:
void updateHeader(CHeader *Hdr)
{
unsigned char cmd = 'A';
unsigned char flag = 'B';
Hdr->SetCommand(cmd);
Hdr->SetFlag(flag);
...
}
Basically, this method simply sets some array values to a certain value.
Afterwards, I create then a pointer to an object of class CHeader and pass it to
the updateHeader function:
CHeader* hdr = new CHeader();
updateHeader(hdr);
In doing this, the program crashes as soon as it executes the Hdr->SetCommand(cmd)
line. Anyone sees the problem, any input would be really appreciated
When you run into a crash, act like a crime investigator: investigate the crime scene.
what is the information you get from your environment (access violation? any debug messages? what does the memory at *Hdr look like? ...)
Is the passed-in Hdr pointer valid?
Then use logical deduction, e.g.:
the dereferencing of Hdr causes an access violation
=> passed in Hdr points to invalid memory
=> either memory wasn't valid to start with (wrong pointer passed in), or memory was invalidated (object was deleted before passing in the pointer, or someone painted over the memory)
...
It's probably SEGFAULTing. Check the pointers.
After
your adding some source code
your comment that the thing runs on another machine
the fact that you use the term 'flag' and 'cmd' and some very small datatypes
making me assume the target machine is quite limited in capacity, I suggest testing the result of the new CHeader for validity: if the system runs out of resources, the resulting pointer will not refer to valid memory.
There is nothing wrong with the code you've provided.
Are you sure the pointer you've created is the same same address once you enter the 'updateHeader' function? Just to be sure, after new() note the address, fill the memory, sizeof(CHeader), with something you know is unique like 0XDEAD, then trace into the updateHeader function, making sure everything is equal.
Other than that, I wonder if it is an alignment issues. I know you're using 8 bit values, but try changing your array to unsigned ints or longs and see if you get the same issue. What architecture are you running this on?
Your code looks fine. The only potential issue I can see is that you have declared a CHeader constructor and destructor in your class, but do not show the implementation of either. I guess you have just omitted to show these, else the linker should have complained (if I duplicate this project in VC++6 it comes up with an 'unresolved external' error for the constructor. It should also have shown the same error for the destructor if you had a... delete hdr; ...statement in your code).
But it is actually not necessary to have an implementation for every method declared in a class unless the methods are actually going to get called (any unimplemented methods are simply ignored by the compiler/linker if never called). Of course, in the case of an object one of the constructor(s) has to be called when the object is instantiated - which is the reason the compiler will create a default constructor for you if you omit to add any constructors to your class. But it will be a serious error for your compiler to compile/link the above code without the implementation of your declared constructor, so I will really be surprised if this is the reason for your problem.
But the symptoms you describe definitely sounds like the 'hdr' pointer you are passing to the updateHeader function is invalid. The reason being that the 1st time you are dereferencing this pointer after the updateHeader function call is in the... Hdr->SetCommand(cmd); ...call (which you say crashes).
I can only think of 2 possible scenarios for this invalid pointer:
a.) You have some problem with your heap and the allocation of memory with the 'new' operator failed on creation of the 'hdr' object. Maybe you have insufficient heap space. On some embedded environments you may also need to provide 'custom' versions of the 'new' and 'delete' operator. The easiest way to check this (and you should always do) is to check the validity of the pointer after the allocation:
CHeader* hdr = new CHeader();
if(hdr) {
updateHeader(hdr);
}
else
//handle or throw exception...
The normal behaviour when 'new' fails should actually be to throw an exception - so the following code will cater for that as well:
try{
CHeader* hdr = new CHeader();
} catch(...) {
//handle or throw specific exception i.e. AfxThrowMemoryException() for MFC
}
if(hdr) {
updateHeader(hdr);
}
else
//handle or throw exception...
}
b.) You are using some older (possibly 16 bit and/or embedded) environment, where you may need to use a FAR pointer (which includes the SEGMENT address) for objects created on the heap.
I suspect that you will need to provide more details of your environment plus compiler to get any useful feedback on this problem.