Memory management is scary. It should be: A lot can go wrong—often very wrong. But a moderately experienced C or C++ programmer can learn and understand memory hazards completely. Once you have that knowledge, you should feel only confidence, not fear. Read the article here.
In the article, the author mentions the below as incorrect … what am I missing because it looks fine to me?
A final model for memory corruption is mistyped dereferencing. This is the category of the buffer overflows that so often yield exploits. Here’s an example:
————————————————
char *bad_implementation_of_strdup(char *string)
{
char *ptr;
/* Oh no! Do you see the missing “+ 1”? */
ptr = (char *) malloc(strlen(string));
strcpy(ptr, string);
return ptr;
}
Think of ptr here as the address of a LENGTH-long character array, while ptr has the distinct type of a (LENGTH + 1) array.
———————————–
Thanks in advance
This should be no news for an average C programmer.
“This should be no news for an average C programmer.”
You’d be surprised with what some people are allowed to get away with in school. They (sinfully) didn’t even teach us malloc() and demalloc(), choosing to start memory management in C++ (with new and delete). Now, mind you, anyone with half a brain can learn malloc and demalloc in an hour, but I’ve seen a lot of idiots out there.
-Erwos
Most of those suggesting that languages which operate within runtimes are somehow superior to languages which compile to native code and don’t include features like automatic garbage collection are prone to a number of problems such as memory leaks and buffer overflows don’t have hands on experience with today’s modern (and in the case of valgrind, free!) memory debuggers.
Again, here we find yet another use for the unit testing stage. Memory leaks and accessing of unallocated memory or memory outside a stack buffer is a programatic error. The next step in unit testing after a particular set of tests succeeds is to rerun those same tests with a memory debugger. A given module of code succeeding to execute unit tests does not indicate that that piece of code is correct for the given range of inputs… it’s only after it’s been memory debugged that you can truly say it’s correct for the given range.
In reality, profile guided optimization places languages which compile to native code well beyond the reaches of any optimizing JIT powered runtime. As long as C++ programmers avoid overuse of virtual classes, especially within loops, and optimize properly with templates, and utilize profile guided optimization, there is no way that any runtime-driven language can even theoretically come close to a native code language.
The goal of any run-time language is clear… to decomplicate the development process by adding additional program complexity. Is this a worthwhile tradeoff? I think when compared to craftsmanlike native code applications, such as qmail, you will find craftsman quality native code applications to be equally as aproblematic from a stability and security standpoint as programs which execute in a runtime environment, but the native code solution will be substantially less complex, and thus arguably more elegant.
string is a C string, which is terminated by a . strlen however gives you the number of characters in the string but not the number of bytes you need to store it. You have to add the terminating to the result of strlen to get the number of bytes the string needs.
ptr points to a chunk of memory which is one byte smaller than the amount of memory strcpy uses to copy the string.
Assume
char *string = “A”;
in effect string has {‘A’, ‘