C++ how to delete local allocated char array? - c++

I wrote a function which receives as a parameter a char pointer,then builds a new dynamic allocated char array that contains that parameter char.Then,it returns the new char array.
This is the function:
char* read_string(char *pstr)
{
char *str;
str = new char[strlen(pstr)];//allocate memory for the new char
str[strlen(pstr)] = '\0';
for(unsigned i=0;i<strlen(pstr);i++)//build the new char
str[i]=pstr[i];
return str;//then return it
}
In main I have:
int main()
{
char *Pchar = read_string("Test");
cout<<Pchar;// Outputs "Test"
delete [] Pchar;//"Program received signal SIGTRAP, Trace/breakpoint trap." error
}
I declare a char pointer in main and then make it point to the char array that is returned from the read_string function.It outputs what I want but if I want to free the memory it gives me runtime error.How can I free up the memory if I don't need to use Pchar anymore?
EDIT:Thank you all for your very informative answers.I have successfully resolved the problem.

You need to allocate more memory to have space for EOS character:
str = new char[strlen(pstr)+1];

Your specific problem is an off-by-one error:
str = new char[strlen(pstr) + 1];
// ^^^^ need one more for the '\0'
str[strlen(pstr)] = '\0';
Generally, since this is C++ and not C, it would be better to return a smart pointer so the caller knows what the ownership semantics of the pointer are:
std::unique_ptr<char[]> read_string(char *pstr)
{
std::unique_ptr<char[]> str(new char[strlen(pstr) + 1]);
// rest as before
return str;
}

It seems that the error occurs due to incorrect length of the allocated string.
You have to use the following record to allocate the string
str = new char[strlen(pstr) + 1];//allocate memory for the new char
str[strlen(pstr)] = '\0';
The function can look the following way
char* read_string( const char *pstr )
{
char *str;
size_t n = strlen( pstr );
str = new char[n + 1];//allocate memory for the new char
strcpy( str, pstr );
return str;
}

Related

Copying a C-style string into memory allocated on free store?

I'm doing an exercise in which I have to copy a c-style string into memory allocated on free store. I am required to do it without using subscripting and relying solely on pointer arithmetic. I wrote the following function-
char* str_dup(const char* s)
{
// count no. of elements
int i = 0;
const char* q = s;
while (*q) { ++i; ++q; }
//create an array +1 for terminating 0
char* scpy = new char[i + 1];
//copy elements to new array
while (*s)
{
*scpy = *s;
++s;
++scpy;
}
*scpy = 0;
return scpy;
}
The function is returning random characters. But if I change it into this-
char* str_dup(const char* s)
{
// count no. of elements
int i = 0;
const char* q = s;
while (*q) { ++i; ++q; }
//create an array +1 for terminating 0
char* scpyx = new char[i + 1];
char* scpy = scpyx;
//copy elements to new array
while (*s)
{
*scpy = *s;
++s;
++scpy;
}
*scpy = 0;
return scpyx;
}
it works. Can someone explain me why first code is not working and second is working?
The first code is not working since you return the final value of scpy, which at that point points at the terminating NUL character, and not the start of the string.
One solution is to do as you did, and save a copy of the original pointer to have something to return.
You should really use strlen() and memcpy(), they make this easier but perhaps they're off-limits to you.

HEAP CORRUPTION DETECTED: after normal block... CRT detected that the application worte to memory after end of heap buffer

When I run this code, I get the error in the title, here's an exact screenshot:
My code is this :
string ProcessCommand(vector<unsigned char> data)
{
try
{
int valread = data.size();
unsigned char* converted = &data[0];
char *buffer = (char *)converted;
buffer[valread] = '\0';
const char file[] = ">myfile.txt";
char * newBuffer = new char[strlen(buffer) + strlen(file) + 1];
strcpy(newBuffer, buffer);
strcat(newBuffer, file);
system(newBuffer);
fstream f("myfile.txt", fstream::in);
string str;
getline(f, str, '\0');
//const char * sendfile = str.c_str();
//char * result;
//result = const_cast<char *>(sendfile);
f.close();
remove("myfile.txt");
return str;
}
catch (const std::exception&)
{
}
}
buffer[valread] = '\0'; is attempting to access an element of buffer that doesn't exist. The program behaviour is therefore undefined.
If you had used data.at(valread) instead then a std::exception would have been thrown (and intercepted at your catch site), as required by the C++11 standard.
Also consider using the + overload of std::string for all your concatenations. Your code will be so much more readable if you do that. Use a std::string type for newBuffer (with automatic storage duration) as well. You can always use c_str() to access the internal data buffer on a read-only basis.

Dynamically allocating character array in class in C++

I'm trying to make my own string class, and I'm trying to create the constructor. So far I'm having a little struggle.
I have my function prototypes defined in a header file and the variable buffer defined in the header file like this char *buffer;, in a new cpp file I'm trying to define the constructor like this:
mystring::mystring(const char *s)
{
int counter = strlen(s)+1;
*buffer = generate_c_array(counter);
}
char * mystring::generate_c_array(int size)
{
return new char[size];
}
I'm basically trying to make it such that buffer is a char array of size s+1 and contains the contents of s followed by a null terminator. Though, this is causing my program to crash.
I'm not sure how to assign buffer correctly, does this look correct?
You can simply write your code
mystring::mystring(const char *s)
{
sz = strlen(s) // sz- another data member, holds size
buffer = new char[sz + 1];
strcpy(buffer, s); // assuming s is null-terminated
}
The for loop and counter were not necessary, in fact
You assign to the specific character in the buffer, not to the variable buffer. Change to:
buffer = generate_c_array(counter);
Other than that, strdup will do the same job for you, but you will have to deallocate with free(). In current code you actually don't really copy, you will have to do strcpy(buffer, s) unless using the strdup mentioned earlier.
Why are you looping over length of the string s?
If you need length of the string use it directly:
std::size_t length = strlen(s);
buffer = generate_c_array(length + 1);
// Copy your string:
memcpy(buffer, s, length)
// Add the terminator character:
buffer[length] = '\0';
You haven't copied the content..
If you want to assign a pointer ( which is what new give you ) to another pointer, you don't need *.
strncpy do the copying for you.
mystring::mystring(const char *s)
{
int counter = strlen(s)+1;
char* buffer = generate_c_array(counter);
strncpy(buffer, s, counter);
}
char * mystring::generate_c_array(int size)
{
return new char[size];
}

How to initialize a char* without first defining it's size

Right off the bat, I'm required to use dynamically allocated character arrays for my assignment, so do NOT suggest I just use strings. I need to create a method that accepts a character array as an argument, and inserts that character into a char* using strcpy. How do I do this without first initializing the char*?
Here is my code so far:
char* char_array;
char test_array[] = {'t','e','s','t','\0'};
strcpy(char_array, test_array);
Your char_array is just an unitialized pointer. You need to dynamically allocate memory for it and then carry out strcpy.
char* char_array = new char[6];
char test_array[] = {'t','e','s','t','\0'};
strcpy(char_array, test_array);
Or as suggested by Joachim you can use strdup() to duplicate a string - it will allocate the memory and copy the string into it.
In both cases, don't forget to free() (or delete[]) the resulting memory once you're done with it.
You can't do that unless you actually allocate a chunk of memory for char_array through malloc or new.
int length = 6;
char* char_array = (char*) malloc(sizeof(char) * length);
or
char* char_array = new char[6];
char * char_array = NULL;
void yourFunc(char your_array[]) {
if (NULL != char_array) {
free(char_array);
char_array = NULL;
}
char_array = (char *)malloc(sizeof(char) * strlen(your_array));
strcpy(char_array, your_array);
}
you stated you need a method/function that accepts a char[]/char *
you have stated your constraints ...
this does seem to be low level for instructional purpose
I assuming null terminated character array and valid source character array
//function accepts character array
char * charseqduplicate(char * s)
{
//low level c
const int len = strlen(s) + 1;;
char * copy = new char[len];
strcpy(copy, s);
//remember to delete or use something like unique_ptr
return copy;
}
void letsdothis()
{
//low level c
char test[] = {'y','e','s',char(0)};
char * dup = charseqduplicate(test);
cout << dup;
delete [] dup;
}

c++ new/delete and char *

Can anyone help me, why I'm getting an error message while trying to free the allocated memory: Heap corruption detected. CTR detected the application wrote the memory after end of heap buffer.
char *ff (char *s){
char *s1 = new char [strlen(s)];
strcpy(s1, s);
return s1;
}
int _tmain(int argc, _TCHAR* argv[])
{
char *s = new char [5];
strcpy(s, "hello");
char *s2 = ff(s);
delete []s; // This works normal
delete []s2; // But I get an error on that line
return 0;
}
char *s = new char [5];
strcpy(s, "hello");
Causes Undefined behavior(UB).
You are writing beyond the bounds of allocated memery. You allocated enough memory for 5 characters but your string has 6 characters including the \0.
Once your program has caused this UB, all bets are off and any behavior is possible.
You need:
char *s = new char [strlen("hello") + 1];
In fact the ideal solution is to use std::string and not char *. These are precisley the mistakes which std::string avoids. And there is no real need of using char * instead of std::string in your example.
With std::string:
You don't need to new anything
You don't need to delete anything &
You can do everything with std::string, that you do with char *.
new char [strlen(s)]; does not count the closing \0 character, so your buffer is too short by one character.
strcpy includes the null terminator; strlen does not. Write:
char *s1 = new char [strlen(s) + 1];
From man strcpy(3):
The strcpy() function copies the string pointed to by src,
including the terminating null byte ('\0'), to the buffer pointed to
by dest.
So you need to reserve 6 bytes 5 for the string and 1 for the NULL byte
char *s = new char [6];
strcpy(s, "hello");
All answers so far have addressed either the first or the second allocation. To sum up, there are two changes you must make:
char *s1 = new char [strlen(s) + 1];
...
char *s = new char [5 + 1];
In both cases, you must allocate enough space for the string plus one byte for the terminating '\0'.
As others already pointed out, with c++ it's easier and safer to use std::string. No fuss with allocation and release of memory or paying attention to '\0' bytes:
std::string ff (const std::string &s){
std::string s1(s);
// do something else with s1
return s1;
}
int main(int argc, char* argv[])
{
std::string s("hello");
std::string s2 = ff(s);
return 0;
}
and if it's just copying the string:
std::string s("hello");
std::string s2(s);
You need to specify char *s1 = new char [strlen(s) + 1]; to make room for the '\0' which terminates the string.
You've corrupted s2 pointer by
strcpy(s, "hello");
Because s has size 5, while you've missed that strcpy includes string terminator.
Your initial string s is only five characters long so can't be null terminated. "hello" will be copied by strcpy including the null-terminator but you'll have overrun the buffer. The strlen needs it to be null terminated so if the null's not there, you'll have problems. Try changing this line:
char *s = new char [6];
Better still, prefer std::string to C style string functions - they're just as efficient and a lot safer and easier to use. Also, try to avoid new and delete unless you really have to use them. The problems you're getting are very common and can easily be avoided.