For some reason compiling the following code with gcc and running the binary it produces on Ubuntu gives a free(): invalid pointer error:
#include <stdlib.h>
#include <fstream>
#include <string>
#include <iostream>
#include <sstream>
#include <ios>
#include <new>
struct arr_double_size {
double *array;
int size;
};
struct Record {
int ID;
std::string str1;
std::string str2;
int num;
struct arr_double_size values;
};
struct Record_array {
struct Record *array;
int size;
};
void Copy_Read(void) {
std::ifstream file{"in_file"};
std::ofstream new_file{"out_file"};
std::string line;
while (std::getline(file,line)) {
new_file << line << std::endl;
}
file.close();
new_file.close();
}
int main(void) {
Copy_Read();
struct Record rec;
struct arr_double_size values;
values.size = 1;
values.array = (double *)malloc(1 * sizeof(double));
values.array[0] = 72.12;
rec.ID = 2718;
rec.str1 = "Test1";
rec.str2 = "Test2";
rec.num = 1;
rec.values = values;
struct Record_array record_list;
record_list.size = 1;
record_list.array = (struct Record *)malloc(1 * sizeof(struct Record));
record_list.array[0] = rec;
return 0;
}
The contents of in_file are:
TEST TEST TEST
Strangely, commenting out the call in main to Copy_Read solves the problem, as does replacing the calls to malloc with calls to new. Running the program with gdb shows that the error occurs when attempting to assign rec to record_list.array[0]. Why does this occur? I have tried to give a minimal example here; previous, expanded versions of this code resulted in segmentation faults instead of the free(): invalid pointer error. I am aware that this is horrible code which should never be used in a serious program (I should be using standard library vector and new), but there seems to be something I do not understand and which is not well-documented (in resources accessible to beginners, anyway) about the difference between malloc and new which is the source of the problems with this code.
I do not understand about the difference between malloc and new
The you need to read much more about C++, e.g. some C++ programming book, and a good C++ reference site. Yes, C++ is a very difficult language (you'll need years of work to master it). Later, you could dive into the C++11 standard n3337 (or some more recent C++ standard). You certainly need to understand precisely the role of constructors and destructors (and explaining that takes many pages, much more than what you can reasonably expect in any StackOverflow answer).
You need to have the code of your constructors to be executed (and that is done with new but not with malloc) - and later the destructors should also be executed, before releasing the memory. Destructors are called by delete (and in many other cases) but of course not by free. Read also about the rule of five and about RAII.
You should, when possible, prefer to use smart pointers. Sometimes (e.g. for circular references) they are not enough.
Be afraid of undefined behavior.
The valgrind tool is useful to hunt memory related bugs. You should also compile with all warnings and debug info, so g++ -Wall -Wextra -g with GCC. You may also want to use static source code analyzers tools such as clang-analyzer or Frama-C. Using them may require a lot of expertise; there is no silver bullet.
Your struct Record_array is wrong: prefer to use std::vector<Record>. Read much more about standard C++ containers.
The constructor of your Record will call the constructor of str1 and of str2 (that it, the constructor of std::string-s applied to two different locations). If you don't call that Record constructor, str1 and str2 stay in some undefined state (so you have some undefined behavior as soon as you use them).
A major difference between malloc & free (for C) and new and delete (for C++) is the way constructors and destructors are involved. Of course, malloc & free are ignoring them, but not new & delete. Failure of memory allocation (e.g. when virtual memory is exhausted) is also handled differently.
PS. In practice, you should never use malloc in C++ code, except -in rare cases only- when defining your own operator new. Because malloc does not call C++ constructors (but new does). Also, please understand that C and C++ are different programming languages, and malloc is for C, not C++. Many C++ standard library implementations are using malloc in their implementation of the standard ::operator new and using free in their ::operator delete.
Related
I have tried to realize set by basic metods via struct.
This is my variant:
#include <iostream>
using namespace std;
struct Set<T> {
int n;
T[n] elements;
}
int main(){
struct Set microSet;
int oneElm, length;
cin>>length;
microSet.n=length;
for(int i=0;i<length;i++) {
cin>>oneElm;
microSet.elements[i]=oneElm;
}
for(int i=0;i<length;i++)
cout << microSet.elements[i];
return 0;
}
Compilator shows me an error related with sruct.
What've I done wrong?
Your code is illegal (and wrong in many places, so take a few days to read a good C++ book then look at some C++ reference website). You can't declare a variable length array as a member of a struct or class (and even if you could, you have the wrong syntax; some compilers support them as an extension, and C99 -but no C++ dialect- has flexible array members).
You'll better use existing standard C++ containers. If you can't use them, you need pointers (and you should prefer smart pointers).
Even if you have some compiler accepting VLAs as an extension, you probably need to dynamically allocate a memory zone for them.
I strongly recommend learning to use containers.
Don't forget to enable all warnings & debug info when compiling. With GCC, compile with g++ -Wall -Wextra -g. Use the debugger (gdb) and perhaps valgrind.
I have copied this code from a site.
But I am having problems understanding it properly.
Please can you help me these doubts.
I have written them as comments.
#include<iostream>
using namespace std;
#include<cstring>
class strings
{
char *m_string;
int m_length;
public:
strings(const char* str = "")
{
m_length = strlen(str) + 1;
m_string = new char[m_length];
strncpy(m_string,str,m_length);
m_string[m_length - 1] = '\0';/*1*/
}
~strings() /*2*/
{
delete[] m_string;
m_string = 0;/*3*/
}
char* get()
{
return m_string;
}
};
int main()
{
strings cstring("Alex");
cout << "Hi I am " << cstring.get();
cout << "\nsup";
strings cstrings1("Shady");
cout << "\nyo " << cstrings1.get();
return 0;
}
why is the code asking me to do this. When I removed this line code still worked perfectly fine
why are they using the destructor? Again not using it does seem to have any effect on the program
Also what is the use of doing this when I just used the delete keyword
Can you guys please explain to me in easy way really what do I use a destructor for? Thank you so much
1) Ensures that the string is null terminated - see http://www.cplusplus.com/reference/cstring/strncpy/ as to why this might not always be the case
2) It allows the delete operator to free up the allocated heap memory - otherwise your program will have a memory leak
3) Just good practice to avoid deleting previously deleted memory - this avoids undefined behaviour.
This is how to misuse C idioms in C++ to produce dangerous, error-prone programs. Don't use this as an example of how to write C++ effectively. To answer your specific questions:
In this case, explicitly terminating the C-style string is pointless. If you didn't know whether the input was small enough to fit in the array, then strncpy might truncate the string, and not put a zero terminator on the end; so, if you use strncpy, you must either terminate it yourself, or take some other action if it was truncated. But here you just allocated a large enough array, measured using strlen. You might as well use strcpy, memcpy or std::copy (which assume a large enough output array) instead of strncpy. Or, since this is C++ not C, throw the whole thing away and use std::string.
The destructor is needed to deallocate the memory allocated in the constructor. Otherwise you have a memory leak. As you say, this doesn't seem to have an effect - unless the program keeps allocating and leaking memory, in which case you'll eventually run out. You'll also need to define or delete a copy constructor and copy-assignment operator (per the Rule of Three), otherwise the class is not safe to copy.
That's pointless, since the pointer itself is about to be destroyed along with the rest of the class object. In some circumstances, if the pointer is going to persist after the delete, setting it to null would allow you to check whether or not it points to anything. But, unless you enjoy long debugging sessions, you shouldn't be using pointers for memory management anyway; use RAII types like smart pointers or std::string.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
Is there a commonly accepted-as-safe approach to wrapping malloc in a function in C++? What I am attempting to do is allocat arbitrarily sized blocks of memory for holding the output of a function that writes binary values into a fixed size buffer (ie: machine instructions). The approach I am currently using is like so:
class voidp {
void *p;
public:
voidp (void *pp) : p (pp) {}
template<class T> operator T *() { return (T *) p; }
};
When converting C to C++, you can define malloc like this:
inline voidp
mymalloc (size_t size)
{
return malloc (size);
}
#define malloc mymalloc
In many cases, it seems like explicit casts to (void*) (at least in the case of my compiler) are not allowed, and I must use the template-based approach above.
Is this approach safe, and are there any implications with respect to the "rule of three" (ie: are there any constructors I need to disable or explicitly define/overload)?
Thank you.
References
My Rant on C++'s operator new - Punching a Whole in the Type System, Accessed 2014-09-05, <http://www.scs.stanford.edu/~dm/home/papers/c++-new.html>
Solve the memory alignment in C interview question that stumped me, Accessed 2014-09-05, <https://stackoverflow.com/questions/227897/solve-the-memory-alignment-in-c-interview-question-that-stumped-me>
Edit
The reason I am doing this is because I'm trying to use something potentially better than just allocating a block of characters via void* buffer = new char[100]. To further elaborate, I am writing some lower-level code that, against my recommendations, must be written in C++, not pure C. I am also required to have dynamic memory allocation methods that create chunks of memory on the heap that are 16-byte, 32-byte, and 64-byte aligned, like in the example below for 16-byte alignment.
{
void *mem = malloc(1024+15);
void *ptr = ((uintptr_t)mem+15) & ~ (uintptr_t)0x0F;
memset_16aligned(ptr, 0, 1024);
free(mem);
}
My application literally creates group of low level machine instructions in blocks which must be 16/32/64 byte aligned (or it will trigger a CPU-level error), and then passes them off to an on-board DSP chip, which runs them as actual instructions, not just input data.
Topic 1: The old good void* ?
C++ has stronger typing than C. It's not a problem, but rather a solution ! The compiler in such way intercept a lot of nasty issues that would take you hours to find out when debugging.
Simple example. The folowing code compiles in C. When I execute I get a core dump.
FILE *fp; // file
void *pbuff; // pointer to buffeer
pbuff = malloc(BUFSIZ);
fp=fopen("test.txt", "rw");
fread(fp, BUFSIZ, 1, pbuff); // ooops !! Did you notice ?
Why ? I inverted fp and pbuff. Both are victims of the void* to anything* and anything* to void* constructs. Of course, experimented programmers don't make such mistakes on standard libraries ! But what with the rest ?
With C++ this erroneous code doesn't compile, because converting void* pbuff to FILE* is recognized as a problem.
Topic 2: Is template voidp a safe practice ?
Well, C++ has classes and inheritence. And a whole bunch of casts to highlight the weird pointer operations you could (and are still allowed to) do. Again C++ eases the bug finding. For example a reinterpret_cast<> deserves more care than a more controlled static_cast<>
To do safe things, one need to understand C++ object model and use the appropriate tools. Your voidp() is very clever, but it's no an appropriate tool for OOP.
Simple example, first the native way:
struct A { std::string name; A(std::string s) : name(s) {} };
struct B : A { int x, y; B(std::string s, int a, int b) : A{ s }, x(a), y(b) {} };
...
A a{ "Chris" };
B b{ "Tophe", 30, 40 };
A *gpa = &a;
B *gpb = &b;
gpa = gpb; // yes, works, because a B is an A and compiler knows it.
//gpb = gpa; // No ! you can't without a recast !
Now with your voidp approach:
voidp pa(&a);
voidp pb(&b);
pb = pa; // no problem.
gpb = pa; // no problem ! Not even a cast to draw attention on potential issue !
So you see, it's rather unsafe ! It really hides nasty errors !
Topic 3: Is malloc() better than new ?
Honnestly, with malloc() you can easily create anything. And it's as easy to create something of the wrong size.... With new, you can also do weird things, but it's more difficult to do basic errors.
new can call the object constructor. With malloc() you need extra steps to do so.
Then, when you have malloc() you have free(). malloc()/free() are excellent for passive data structures that you have in C. But in C++, when you want get rid of an object properly, you have to destoy is. So delete is really more appropriate .
Conclusion
I've read your reference with interest. It's true, that new has limitations.
But I don't share the article's conclusions. Instead of avoiding new and switch back to malloc() (again: it's perfect for C code, but simply not the best fit for C++), it would be a better way to investigate the standard library and for example use shared_ptr<> and other smart pointers. These are much better for avoiding memory leaks, than rewriting one own version of malloc...
Edit
The specific use that you make could be done in C++ as well
char buffer[1024 + 15]; // allocation on stack, or char *mem = new char[1024+15]
char *ptr = reinterpret_cast<char*>(((uintptr_t)&buffer + 15) & ~(uintptr_t)0x0F); // Yes
std::fill_n(ptr, 0, 1024); // is memset_16aligned() really portable ?
// nothing if on stack // or delete[] mem if new was used
There exist also the function std::align() that does the calculation you do for ptr.
And there is a placement-new to allocate a C++ object on a fixed address, for example:
char* p = new(ptr)char[1024]; // of course you shouldn't delete this one
If you're writing C++ code. You should use new and delete. Writing C style in C++ is generally bad practice, as the C++ compiler will not produce optimal binaries. If you find yourself doing a lot of type casting with void*, you're probably doing it wrong.
Conversely, use C++11 smart pointers!
The new and delete are for low level library development.
There are STL containers available for buffer allocation and de-allocation.
In your case, you may try
std::vector<unsigned char> myBuffer(MAX_SIZE);
Running Valgrind against an existing codebase, I am getting a lot of "Mismatched free / delete/ delete[]" errors. Many of them are a repeat of one problem: it claims that at line XXX a delete operation is being used, whereas at line YYY a malloc operation is used. However, when I open the file that it complains about and navigate to the line numbers indicated, I find that the memory was not allocated with malloc but with new. The allocated object was an standard ifstream and neither new[] nor delete[] are being used.
I'm running Valgrind 3.5. Does anyone have any idea what is happening? I cannot see how this can be a real error, but I've seen some people claim that Valgrind doesn't turn up many false positives, so I want to have some confidence that this is fake before suppressing it.
You don't provide a sample program, so this is a crystal-ball guess.
Your program provides an operator new but is missing an operator delete. The following sample program produces the same error message you are seeing:
#include <new>
#include <cstdlib>
/*
* Sample program that provides `operator new`, but not `operator delete`.
*/
// minimal version of new for demonstration purpose only
void* operator new(size_t numBytes) {
return malloc(numBytes);
}
int main () {
int *p = new int;
delete p;
}
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
How could pairing new[] with delete possibly lead to memory leak only?
I was always told that it's not safe to call delete on an array allocated with new[]. You should always pair new with delete and new[] with delete[].
So I was surprised to discover that the following code compiles and runs ok, in both Debug and Release mode under VS2008.
class CBlah
{
public:
CBlah() : m_i(0) {}
private:
int m_i;
};
int _tmain(int argc, _TCHAR* argv[])
{
for(;;)
{
CBlah * p = new CBlah[1000]; // with []
delete p; // no []
}
return 0;
}
It took me a while to figure out why this works at all, and I think it's just luck and some undefined behaviour.
BUT... it made me wonder... why doesn't Visual Studio pick this up, at least in the Debug memory manager? Is it because there's lots of code out there that makes this mistake and they don't want to break it, or do they feel it's not the job of the Debug memory manager to catch this kind of mistake?
Any thoughts? Is this kind of misuse common?
It will certainly compile ok, because there is no information in the pointer (compile-time) which will see if pointer points to array or what. For example:
int* p;
cin>>x;
if(x == 0)
p = new int;
else
p = new int [10];
delete p; //correct or not? :)
Now , about running ok. This is called undefined behavior in C++, that is, there is no guarantee what will happen - everything can run OK, you can get a segfault, you can get just wrong behavior, or your computer may decide to call 911. UB <=> no guarantee
It's undefined behavior and everything is fair in love, war and undefined behavior...:)
According to MDSN, it translates delete to delete[] when trying to delete an array. (See there, for instance). Though you should have a warning after compiling.
The reason the Debug Memory Manager does not pick up on this error is probably because it it not implemented at the level of new/delete, but at the level of the memory manager that gets invoked by new/delete to allocate the required memory.
At that point, the distinction between array new and scalar new is gone.
You can read these SO answers and links about delete and delete[]: About delete, operator delete, delete[], ...
I don't know what makes you think it "works ok". It compiles and completes without crashing. That does not mean necessarily there was no leak or heap corruption. Also if you got away with it this time, it doesn't necessarily make it a safe thing to do.
Sometimes even a buffer overwrite is something you will "get away with" because the bytes you have written to were not used (maybe they are padding for alignment). Still you should not go around doing it.
Incidentally new T[1] is a form of new[] and still requires a delete[] even though in this instance there is only one element.
Interesting point.
Once I did a code review and tried to convince programmers to fix new[]-delete mismatch.
I've argumented with "Item 5" from Effective C++ by Scott Meyers. However, they argumented with "What do you want, it works well!" and proved, that there was no memory leakage.
However, it worked only with POD-types. Looks like, MS tries to fix the mismatch as pointed out by Raveline.
What would happen, if you added a destructor?
#include <iostream>
class CBlah
{
static int instCnt;
public:
CBlah() : m_i(0) {++instCnt;}
~CBlah()
{
std::cout <<"d-tor on "<< instCnt <<" instance."<<std::endl;
--instCnt;
}
private:
int m_i;
};
int CBlah::instCnt=0;
int main()
{
//for(;;)
{
CBlah * p = new CBlah[10]; // with []
delete p; // no []
}
return 0;
}
Whatever silly"inteligence" fix is added to VS, the code is not portable.
Remember that "works properly" is within the universe of "undefined behavior". It is quite possible for a particular version of a particular compiler to implement this in such a way that it works for all intents and purposes. The important thing to remember is that this is not guaranteed and you can't really ever be sure it's working 100%, and you can't know that it will work with the next version of the compiler. It's also not portable, since another compiler might work in a different fashion.
This works because the particular C++ runtime library it was linked with uses the same heap for both operator new and operator new[]. Many do, but some don't, which is why the practice is not recommended.
The other big difference is that if CBlah had a non-trivial destructor, the delete p; would only call it for the first object in the array, whereas delete[] p; is sure to call it for all the objects.