How to copy a byte[] into a char*? - c++

All I need this for is strcpy().
I want to see whether the first three bytes of a buffer(byte array) are "JMX" as string.
This is what I did so far:
char * ddj;
strcpy( ddj, buffer ); //buffer is BYTE[]
if ( strcmp( "JMX", ddj ) == 0 ) //check first three chars are "JMX"
{
buffer += 20; //increase the index with 20
size -= 20; //int
}
I get exception at strcmp() line. What is the problem?
I wish I was writing this in C# :(

Tho things go wrong here:
ddj does not point to any actual memory. Hence the copy will have undefined behavior
The copying is not necessary in the first place.
This is what you can do:
if(strncmp("JMX", buffer, 3) == 0) {
buffer += 20;
size -= 20;
}
This uses strncmp instead of strcmp, thus ensuring that no more than three bytes are compared. If buffer can contain less than three bytes, you should do something like:
if(buf_len >= 3 && strncmp("JMX", buffer, 3) == 0) {
buffer += 20;
size -= 20;
}

You're not allocating any memory for ddj. Since it's a local variable, it's allocated on the stack. Local variables are not initialized to 0/false/NULL by default, so the value of ddj immediately after it's declared is undefined -- it will have the value of whatever is left in memory at that particular location on the stack. Any attempt to dereference it (that is, to read or write the memory at which it's pointing) will have undefined behavior. In your case, it's crashing because it's pointing to an invalid address.
To fix the problem, you need to allocate storage for ddj. You can either allocate static storage on the stack, or dynamic storage on the heap. To allocate static storage, do:
// Allocate 64 bytes for ddj. It will automatically be deallocated when the function
// returns. Be careful of buffer overflows!
char ddj[64];
To allocate dynamic storage:
// Allocate 64 bytes for ddj. It will NOT be automatically deallocated -- you must
// explicitly deallocate it yourself at some point in the future when you're done
// with it. Be careful of buffer overflows!
char *ddj = new char[64];
...
delete [] ddj; // Deallocate it
Instead of managing storage yourself, it would be a better idea to use std::string, which automatically deals with memory management.
Finally, since all you're doing is comparing the first three characters of the string, there's no need to jump through hoop to copy the string and compare it. Just use strncmp():
if(strncmp(buffer, "JMX", 3) == 0)
{
...
}

You have not allocated memory for ddj. Allocate memory using new to it . For example
char *ddj = new char[size]; //Allocate size number of chars
//do the required comaprisons
delete[] ddj; //Remember to release the memory.
On the other hand you can use std::string which is a standard string class.

You must allocate new memory for ddj. Either declare it as
char ddj[NAX_LENGTH];
or with dynamic allocation
char* ddj = new char[length]; // You must use delete[] to free the memory in the end.
A more convenient alternative is std::string.

Firstly, it's crashing because ddj doesn't point to anything.
Secondly, you don't need to copy the data from byte[] to char* (they're essentially the same thing). You can just do:
if (strncmp("JMX", reinterpret_cast<char*>(buffer), 3) == 0)
{
// Strings are equal, do what you want
}

This is UB because ddj isn't pointing to anything. You need to allocate memory:
char* ddj = new char[strlen(buffer) + 1];
Be sure to delete the memory you allocated using delete[] (not plain delete!).
You could also use std::string which is generally safe, as you don't have to deal with pointers and memory alloation.
Looking at your code, however, ddj seems useless. Just use buffer:
if ( strcmp( "JMX", buffer ) == 0 ) //check first three chars are "JMX"
{
buffer += 20; //increase the index with 20
size -= 20; //int
}

You are getting the exception because the variable 'ddj' isn't initialized. It is pointing at garbage, so who knows where you are copying that string...
You don't really need to copy the bytes before comparing them, though.
if(strncmp("JMX", buffer, 3) == 0) // check if the first three characters are "JMX"
{
buffer += 20;
size -= 20;
}

if you want to strcmp ddj, you can also do it on buffer first, and make a copy of buffer if you need it later.

Related

Would setting a char to '\0' leak memory?

char myStr[] = "Hello World";
char *p = strchr(myStr, 'W');
*p = '\0';
// Now myStr would be "Hello ";
If I do something like this, would this leak memory for "orld" part?
No, because in C, strings are just pre-defined char arrays that are terminated with the '\0' character. All the space for the string of characters is pre-allocated at run time and is inflexible unless you reassign the variable to point to a different section of memory, which is outside of the scope of this question.
In your example you initialize a char array to "Hello World" which is 12 bytes counting the \0 character at the end. Those 12 bytes are yours to use until the program finishes and will not be lost by conventional means. Resetting the contents of the string is as simple as writing different values to the char array. As long as your data does not exceed the limits of the array, you will not run into any issues or memory leaks.
Hope this helps.
Would setting a char to '\0' leak memory?
Generally, no.
A resource leak happens when you lose a handle to the resource. For example, when you allocate memory with malloc, you get a pointer that must be passed to free in order to release the memory. If you lose the pointer value, then you can never free the memory. That is a memory leak.
In the example program, you have an array with automatic storage, which contains the elements ['H','e','l','l','o',' ','\0','o','r','l','d','\0'. It is destroyed and its memory is released automatically when it goes out of scope.
Consider:
char myStr[] = "Hello World";
char *p = strchr(myStr, 'W');
*p = '\0';
printf( "Length of myStr = %d\n", strlen( myStr ) ) ;
printf( "Size of myStr = %d\n", sizeof( myStr ) ) ;
The output will be:
Length of myStr = 0
Size of myStr = 12
The size of an array and the length of a string are not the same thing. A string in C is not a data type, it is merely adjacent characters terminated by NUL. A string in C is contained in an array or block of contiguous memory that must be at least as long as the string plus 1 (to accommodate the NUL).
There is no memory leak or even "loss" because you can at any time access the entirety of the myStr array's 12 bytes.
In any event a memory leak occurs when you fail to return a dynamically allocated memory block to the heap. Since myStr is not dynamically allocated, it cannot "leak". Even if it were, modifying its content cannot cause a leak - although over/under running the allocation might by corrupting the heap.
Memory leak occurs when you no longer have a reference to an allocated memory that is not automatically freed.
Assigning a value to an array element does not cause memory leak because that doesn't lose you the reference to the array.
In your case, the array has automatic storage duration if it has function scope, so when it runs out of scope, it is de-allocated automatically.
But even if you had a dynamically allocated array, the assignment won't lose you the address of the allocated memory, so no leak.

Memory Leak (char[])

When I run my program, it can run for a while, then all of the sudden, it experiences a huge memory leak. I traced it out using a snapshot of the heap when it crashed, and I have a mysterious char[] with the size of 232,023,801 Bytes. The minutes preceding crash have no unusual behavior until then. The only places where I use char arrays is in the following piece of code:
string ReadString(DWORD64 addr) {
char* buffer = new char[128];
bool validChar = true;
for (int c = 0; c < 128 && validChar; c++) {
buffer[c] = Mem.Read<char>(addr+ (0x1 * c), sizeof(char));
if (!isalnum(buffer[c]) && !ispunct(buffer[c]))
validChar = false;
}
string ret= string(buffer);
delete[] buffer;
return ret;
}
All this code should be doing is reading a few characters from memory, saving the char array to a string, cleaning up the array, and returning the string. How is the memory leak originating from here? Or does the char[] in the heap snapshot potentially point to another issue?
Assuming that string here is std::string:
You call string(buffer) which assumes that buffer is 0-terminated and allocates a new string. But your code doesn't ensure that buffer is actually 0-terminated, so this can cause undefined behavior, including potentially crashing or allocating too much memory for the string.
You probably want to use the string(buffer, size) constructor instead, which doesn't require buffer to be 0-terminated.
I'd also recommend avoiding the manual new/delete. One way to do this is to create an empty string and push_back the characters you read to it. This avoid the need for buffer.

Heap corruption error in Visual Studio while freeing dynamic memory

I am having an issue with a function that concatenates a number to the end of a char array. I honestly can't see the issue:
void x(int num, char* originalArray) {
char* concat_str = new char[1];
sprintf(concat_str, "%d", num);
for (int i = 0; i < 1; i++)
originalArray[i + 10] = concat_str[i];
delete [] concat_str;
}
The error message is:
HEAP CORRUPTION DETECTED: after Normal block (#147) at 0x01204CA0. CRT detected that the application wrote to the memory after the end of heap buffer.
Any ideas? I'm a beginning programmer, but I've done this same kind of thing many times and never had this issue. Thanks.
concat_str needs to be large enough to hold the number of digits in num plus a null terminator. Since it size is one you only have enough room for the null terminator. Trying to add anything else is undefined behavior as it accesses memory you do not own and causing the heap corruption.
You're allocating one byte for concat_str, and sprintf'ing something that requires more space than that.
First of all, note that your API is a C api. If you want a dynamic array in C++, use std::vector<char>.
But, assuming you need to stick to the C API, there's no way to guarantee that your originalArray is large enough to hold the result. Furthermore, the temporary buffer is unnecessary.
You should modify the API and the implementation as follows:
Take the size of the destination, to guarantee that it doesn't write past its end.
Write the string in place in the destination buffer. Putting it into a temporary buffer and then copying to the destination is a waste of time.
Use snprintf, not sprintf. The latter is not safe: you can't guarantee it won't write past the end of your buffer.
You should assert the precondition that the offset is at least smaller than the destination size.
If the precondition holds, the destination will be always properly zero-terminated, although the text representation of num might not fit in it.
You can return the length of the destination that is necessary for the value to fit.
Thus:
size_t fun(int num, char * dest, size_t dest_size) {
const size_t offset = 10;
assert(dest_size > offset);
return offset + snprintf(dest + offset, dest_size - offset, "%d", num);
}

c++: Does the new operator for dynamic allocation check for memory safety?

My question arises from one of my c++ exercises (from Programming Abstraction in C++, 2012 version, Exercise 12.2). Here it is:
void strcpy(char *dst, char *src) {
while (*dst++ = *src++);
}
The definition of strcpy is dangerous. The danger stems from the fact
that strcpy fails to check that there is sufficient space in the
character array that receives the copy, thereby increasing the chance
of a buffer-overflow error. It is possible, however, to eliminate much
of the danger by using dynamic allocation to create memory space for
the copied string. Write a function
char *copyCString(char *str);
that allocates enough memory for the C-style string str and then
copies the characters—along with the terminating null character—into
the newly allocated memory.
Here's my question:
Is this new method really safe? Why it's safe?
I mean, to be a little bit radical, what if there isn't enough space in the heap?
Is the new operator able to check for space availability and fall in an elegant way if there isn't enough space?
Will that cause other kind of "something-overflow"?
If new fails to allocate the requested memory, it's supposed to throw a std::bad_alloc exception (but see below for more). After that, the stack will be unwound to the matching exception handler, and it'll be up to your code to figure out what to do from there.
If you really want/need to assure against an exception being thrown, there is a nothrow version of new you can use that will return a null pointer to signal failure--but this is included almost exclusively for C compatibility, and not frequently used (or useful).
For the type of situation cited in the question, you normally want to use std::string instead of messing with allocating space yourself at all.
Also note that on many modern systems, the notion of new either throwing or returning a null pointer in case of failure, is really fairly foreign. In reality, Windows will normally attempt to expand the paging file to meet your request. Linux has an "OOMKiller" process that will attempt to find "bad" processes and kill them to free up memory if you run out.
As such, even though the C++ standard (and the C standard) prescribe what should happen if allocation fails, that's rarely what happens in real life.
New operator will throw bad_alloc exception if it cannot alocate memory, unless nothrow specified. If you specify constant nothrow you will get NULL pointer back if it cannot alocate memory.
The code for strcpy is unsafe because it will try copying outside of the allocated memory for the dst pointer. Example:
int main()
{
const char* s1 = "hello"; // allocated space for 6 characters
char* s2 = new char[ 2 ]; // allocated space for 2 characters.
strcpy( s2, s1 );
cout << s2 << endl;
char c; cin >> c;
return 0;
}
This prints the correct value "hello", but remember that the pointer s2 was allocated to only have space for 2 characters. So we can assume that the other characters were written to the subsequent memory slots, which is unsafe as we could be overwriting data or accessing invalid memory.
Consider this solution:
char* e4_strdup( const char*& c )
{
// holds the number of space required for the c-string
unsigned int sz{ 0 };
// since c-style strings are terminated by the '\0' character,
// increase the required space until we've found a '\0' character.
for ( const char* p_to_c = c; *p_to_c != '\0'; ++p_to_c )
++sz;
// allocate correct amount of space for copy.
// we do ++sz during allocation because we must provide enough space for the '\0' character.
char* c_copy{ new char[ ++sz ] }; // extra space for '\0' character.
for ( unsigned int i{ 0 }; i < sz; ++i )
c_copy[ i ] = c[ i ]; // copy every character onto allocated memory
return c_copy;
}
The new operator will still return a std::bad_alloc exception if you run out of memory.

Deleting a non-owned dynamic array through a pointer

I'm relatively novice when it comes to C++ as I was weened on Java for much of my undergraduate curriculum (tis a shame). Memory management has been a hassle, but I've purchased a number books on ansi C and C++. I've poked around the related questions, but couldn't find one that matched this particular criteria. Maybe it's so obvious nobody mentions it?
This question has been bugging me, but I feel as if there's a conceptual point I'm not utilizing.
Suppose:
char original[56];
cstr[0] = 'a';
cstr[1] = 'b';
cstr[2] = 'c';
cstr[3] = 'd';
cstr[4] = 'e';
cstr[5] = '\0';
char *shaved = shavecstr(cstr);
// various operations, calls //
delete[] shaved;
Where,
char* shavecstr(char* cstr)
{
size_t len = strlen(cstr);
char* ncstr = new char[len];
strcpy(ncstr,cstr);
return ncstr;
}
In that the whole point is to have 'original' be a buffer that fills with characters and routinely has its copy shaved and used elsewhere.
To clarify, original is filled via std::gets(char* buff), std::getline(char* buff, buff_sz), std::read(char* buff, buff_sz), or any in-place filling input reader. To 'shave' a string, it's basically truncated down eliminating the unused array space.
The error is a heap allocation error, and segs on the delete[].
To prevent leaks, I want to free up the memory held by 'shaved' to be used again after it passes through some arguments. There is probably a good reason for why this is restricted, but there should be some way to free the memory as by this configuration, there is no way to access the original owner (pointer) of the data.
I assume you would replace original by cstr, otherwise the code won't compile as cstr is not declared.
The error here is that the size of the allocated array is too small. You want char* ncstr = new char[len+1]; to account for the terminating \0.
Also, if you delete shaved right after the function returns, there is no point in calling the function...
[*] To go a bit deeper, the memory used for cstr will be released when the containing function returns. Usually such static strings are placed in constants that live for the entire duration of the application. For example, you could have const char* cstr="abcde"; outside all your functions. Then you can pass this string around without having to dynamically allocate it.
Assuming you meant to use cstr instead of cstrn...
You should not be deleting cstr. You should be deleting shaved.
You only delete the memory that was allocated with new. And delete[] memory that was allocated with new[].
shaved is simply a variable that holds a memory address. You pass that memory address to delete[] to get rid of the memory. shaved holds the memory address of the memory that was allocated with new[].