strcpy throws memory exception - c++

#include<stdio.h>
#include<string.h>
#include<iostream.h>
using namespace std;
int main()
{
const char *a="hello";
char *b;
strcpy(b,a);
cout<<b;
return 0;
}
This code theows memory exception . why ?

char* b is a pointer that is yet to be pointed at any memory... it simply holds a random address. You attempt to copy the content of a over the memory at that address. Instead, first point b at some memory - either a local array or from new char[].
char buffer[128];
char* b = buffer;
char* b = new char[128];
// use b for a while...
delete[] b; // release memory when you've finished with it...
// don't read/write data through b afterwards!
( or simply copy it directly into buffer :-) )
BTW, C++ has a <string> header that's much, much easier to use:
#include <string>
int main()
{
std::string s = "hello";
std::string t = s;
std::cout << t << '\n'; // '\n' is a "newline"
}
If you're writing new code, prefer std::string, but sooner or later you'll need to know about all that char* stuff too, especially when C++ code needs to interact with C libraries.

Exception is due to uninitialized,
char *b;
Either allocate b on stack as an array,
char b[SIZE];
Or allocate using new and later delete it. But the best way is,
std::string b;
b = a;

Here
char *b;
strcpy(b,a);
b is not initialized - using its value is undefined behavior. Even if using its value is okay on your platform it holds "whatever" address - copying a string onto "whatever address" is undefined behavior.
You have to allocate a memory block by any legal means and set b to start of that block. The block must be large enough to hold the string together with terminating null character.

b is uninitialised. It is a pointer, but it doesn't point anywhere (it holds NULL or a garbage value). strcpy tries to write to it, but it must have a pointer to write to. You must assign some chunk of memory to b before you can use it. Eg:
char *b = new char[20]; //dynamically allocate some memory
or
char b[20]; //allocate some memory on the stack

A few things are "wrong" with your code.
Use:
#include <iostream>
You're not using C++ strings.
std::string a = "hello";
std::string b = a;
If you insist on using strcpy(), please allocate some memory for b:
b = new char[strlen(a)];
// Your code here
delete[] b;
There's lots of memory to go around. No need to go about corrupting stuff.

You need to allocate memory (e.g. using malloc) for the destination before you can copy something there.

The char pointer b is initiaized to 0 when the program runs. So you can't copy anything to it.
If you want to copy a string, in C++ style, do this instead:
#include<iostream>
#include<string>
using namespace std;
int main()
{
string a = "hello";
string b = a;
cout << b << endl;
return 0;
}

strcpy(dest, source)
In your code b is your dest and it is not initialized. Even if you switch them around it will still crash because you have not allocated memory for b. The destination memory has to be pre-allocated.

Related

C++ Object Copy

I'm just looking at the following code snippet:
#include<iostream>
#include<cstring>
using namespace std;
class String
{
private:
char *s;
int size;
public:
String(const char *str = NULL); // constructor
~String() { delete [] s; }// destructor
void print() { cout << s << endl; }
void change(const char *); // Function to change
};
String::String(const char *str)
{
size = strlen(str);
s = new char[size+1];
strcpy(s, str);
}
void String::change(const char *str)
{
delete [] s;
size = strlen(str);
s = s + 1;
s = new char[size+1];
strcpy(s, str);
}
int main()
{
String str1("StackOverFlow");
String str2 = str1;
str1.print();
str2.print();
str2.change("StackOverFlowChanged");
str1.print();
str2.print();
return 0;
}
I expect the output as:
StackOverflow,
StackOverflow,
StackOverflow,
StackOverflowChanged.
Before str2.change("StackOverFlowChanged") line, both str1 and str2's s point to the same memory location. However, in change method, since the pointer value changed, I except now str1 and str2's s point to the different locations and this is not the case. Can somebody explain why this is the case?
After calling str2.change, str1 no longer has a valid pointer. Since the two objects were sharing the same pointer, by deleting the array in one object, the other object now points to a deleted array. Attempting to access the array pointed to by str1 is undefined behavior, so str1.print() is invalid code.
Now, in this particular case, odds are good that the new char[] in str2.change just so happens to return a pointer to an address identical to the one that was just deleted. After all, the memory was just freed up, and no other allocations were made in the meantime. So while str1's pointer is still invalid, it just so happens to work out to pointing at a valid string by the time str1.print gets called.
But that's just happenstance; an implementation didn't have to do that. Undefined behavior is undefined, and you need to properly follow the Rule of 5. Or just use std::string.
The problem is that you called delete[] on the memory pointed by str1.
The runtime library is then allowed to reuse the same memory for the next allocation call and apparently this is what happened.
str1 didn't change the memory it pointed to, but the content changed.
Note that using a pointer to memory after it has been delete[]d is undefined behavior. So indeed anything can happen.
When you write classes that own heap allocated memory a lot of care should be taken about who owns the memory and when this memory is going to be released; in particular a lot of attention should go to copy constructor and assignment operator because the automatically generated code is rarely the correct one in case of memory owned using raw pointers.
No, str1 and str2 do not point to the same memory location, before str2.change("StackOverFlowChanged") line. str2 is in a different location but with the same value as of str1. You can verify this using -
cout << &str1 << '\t' << &str2 << endl;
It will show that they have different locations in memory.

c++ how to free memory *char?

How to free memory with something like this (Visual Studio 2008 - Win32/console):
I can include only: iostream
#include <iostream>
void data_t(char *test[])
{
test[0] = new char[];
test[1] = new char[];
test[0] = "Test1";
test[1] = "Test2";
}
int main()
{
char *test[2];
data_t(test);
cout<<test[0]<<"\n";
cout<<test[1]<<"\n";
delete[] test[0];//Debug assertion failed! - The program '[7884] Zadanie_4_sortowanie.exe: Native' has exited with code 3 (0x3).
delete[] test[1];
}
What i do wrong?
test[0] contains a pointer to the static string "Test1", which cannot be deallocated. Use strcpy to copy C strings.
char[] is an incomplete type, and cannot be used in a new expression. You need to actually decide on an array size, like:
char * p = new char[200];
Then you can say delete[] p; when you're done.
You will need something like strcpy to copy data into the char array. The assigment you wrote only overwrites the pointer, thus losing track of the dynamic allocation (i.e. leaking). (In fact, you might not need dynamic allocation at all if you just want fixed strings, so just remove the lines with new and delete in them.)
What you really want, though, is a std::array<std::string, 2>, though:
#include <array>
#include <string>
#include <iostream>
std::array<std::string, 2> test = { "Test1", "Test2" };
std::cout << test[0] << "\n" << test[1] << "\n";
Or pass it by reference:
void populate(std::array<std::string, 2> & a)
{
a[0] = "Test1";
a[1] = "Test2";
}
int main()
{
std::array<std::string, 2> test;
populate(test);
// print ...
}
Since "Test1" and "Test2" are used by your program at runtime (they are printed by cout), the compiler has to save them somewhere. It does this by putting them both into your executable.
Since they are both in your executable already, there is no reason to allocate any new memory.
So you can remove the first two lines in data_t.
If you do this you will get a compiler error, though this error should have already been there, which will complain that you are trying to assign a string literal ("Test1", "Test2") to a non const array.
The problem here is that strings saved by the compiler into the executable are NOT to be modified. You are only printing them, but data_t doesn't know that. To fix the problem you should use const char * instead of char *
If you intend to modify these strings, you'll need to allocate new memory and copy the strings into it.

Initialization of c++ heap objects

I'am wondering if built-in types in objects created on heap with new will be initialized to zero? Is it mandated by the standard or is it compiler specific?
Given the following code:
#include <iostream>
using namespace std;
struct test
{
int _tab[1024];
};
int main()
{
test *p(new test);
for (int i = 0; i < 1024; i++)
{
cout << p->_tab[i] << endl;
}
delete p;
return 0;
}
When run, it prints all zeros.
You can choose whether you want default-initialisation, which leaves fundamental types (and POD types in general) uninitialised, or value-initialisation, which zero-initialises fundamental (and POD) types.
int * garbage = new int[10]; // No initialisation
int * zero = new int[10](); // Initialised to zero.
This is defined by the standard.
No, if you do something like this:
int *p = new int;
or
char *p = new char[20]; // array of 20 bytes
or
struct Point { int x; int y; };
Point *p = new Point;
then the memory pointed to by p will have indeterminate/uninitialized values.
However, if you do something like this:
std::string *pstring = new std::string();
Then you can be assured that the string will have been initialized as an empty string, but that is because of how class constructors work, not because of any guarantees about heap allocation.
It's not mandated by the standard. The memory for the primitive type members may contain any value that was last left in memory.
Some compilers I guess may choose to initialize the bytes. Many do in debug builds of code. They assign some known byte sequence to give you a hint when debugging that the memory wasn't initialized by your program code.
Using calloc will return bytes initialized to 0, but that's not standard-specific. calloc as been around since C along with malloc. However, you will pay a run-time overhead for using calloc.
The advice given previously about using the std::string is quite sound, because after all, you're using the std, and getting the benefits of class construction/destruction behaviour. In other words, the less you have to worry about, like initialization of data, the less that can go wrong.

What is the best practice of using itoa()

When I use itoa() it needs a char* _DstBuff, what is the best practice here?
#include "stdafx.h"
#include <iostream>
using namespace std;
int main()
{
int num = 100;
// I'm sure here is no memory leak, but it needs to know the length.
char a[10];
// will this causue memory leak? if yes, how to avoid it?
// And why can itoa(num, b, 10); be excuted correctly since b
// has only allocated one char.
char *b = new char;
// What is the difference between char *c and char *b
// both can be used correctly in the itoa() function
char *c = new char[10];
itoa(num, a, 10);
itoa(num, b, 10);
itoa(num, c, 10);
cout << a << endl;
cout << b << endl;
cout << c << endl;
return 0;
}
the output is:
100
100
100
So could anyone explain the differenct between char *b = new char; and char *c = new char[10]; here?
I know char *c will dynamiclly allocate 10 chars, but that means char *b will only dynamically allocate 1 char, if I'm right about this, why is the output all correct?
actually which is the best practice of a, b, or c?
Best practice: Don't use it at all.
Why? Because it's not in the standard.
What should I do instead? Use std::to_string.
(If you're really stuck having to use itoa, then use a large local static buffer, like char[512] or so -- if you want to be really really safe you can make the array size sizeof(unsigned long long int) * CHAR_BIT + 2 or something like that so it can always hold any number expressed in any base, plus sign.)
In this question I posed, you'll find a dozen efficient functions for converting an integer into a string, all of which allocate and return a std::string so you needn't worry about buffer overflow. And several options in there are blistering fast.
What you are describing is not a memory leak, but rather a buffer overflow.
Basically, you are getting lucky. If you allocate only one character, but then write four characters to it, you are overrunning what has been allocated to you, and this is a bug.
cout << b << endl; : is incorrect, it is a buffer overflow.
because you allocate 1 byte of memory to contain one char. but, you write on it with itoa() 10+1chars.
so you have to allocate : char * d = new char[11]; // 10 chars + '\0'(end of string char).
then use itoa(num , d , 10);
in addition itoa() is non standard, so i prefer to use the standard sprintf(d,"%d",num);
and as said in the comment below, if you dont need char* and you can use std::string. use
string d = std::to_string(num);

C++: Trouble with Pointers, loop variables, and structs

Consider the following example:
#include <iostream>
#include <sstream>
#include <vector>
#include <wchar.h>
#include <stdlib.h>
using namespace std;
struct odp {
int f;
wchar_t* pstr;
};
int main()
{
vector<odp> vec;
ostringstream ss;
wchar_t base[5];
wcscpy_s(base, L"1234");
for (int i = 0; i < 4; i++)
{
odp foo;
foo.f = i;
wchar_t loopStr[1];
foo.pstr = loopStr; // wchar_t* = wchar_t ? Why does this work?
foo.pstr[0] = base[i];
vec.push_back(foo);
}
for (vector<odp>::iterator iter = vec.begin(); iter != vec.end(); iter++)
{
cout << "Vec contains: " << iter->f << ", " << *(iter->pstr) << endl;
}
}
This produces:
Vec contains: 0, 52
Vec contains: 1, 52
Vec contains: 2, 52
Vec contains: 3, 52
I would hope that each time, iter->f and iter->pstr would yield a different result. Unfortunately, iter->pstr is always the same.
My suspicion is that each time through the loop, a new loopStr is created. Instead of copying it into the struct, I'm only copying a pointer. The location that the pointer writes to is getting overwritten.
How can I avoid this? Is it possible to solve this problem without allocating memory on the heap?
What you've got here is undefined behavior. Each time through your loop you create and destroy an array and then assign its address to foo.pstr and push it back into your vector. The compiler just happens to create that array in the same place every time (which is logical but not necessary). When you print it out you're technically printing out deleted data it's just that the system isn't bitch slapping you for it because it's not protected space. The memory location simply has whatever it was assigned last.
You fix this by discontinuing the use of raw character pointers and arrays.
...
odp foo;
foo.f = i;
wchar_t loopStr[1]; //A
foo.pstr = loopStr; //B
foo.pstr[0] = base[i]; //C
vec.push_back(foo);
...
A - You allocate an array (of size 1) to the stack
B - You assign foo.pstr to point to the array on the stack
C - You assign base[i] to the first element of the array (which is on the stack)
After the for loop exits its current cycle the variable loopStr is no longer in scope and its content is undefined. The next loop iteration will most likley re-use the same memory address (hence why you get the same value when you print at the end). If you have optimisations turned on your C compiler may be able to warn you about taking addresses of local variables (although I doubt it).
Without using any heap allocation I would think your only option is to fix the size of foo.pstr in odp, i.e.
struct odp {
int f;
wchar_t pstr[1];
};
or allocate the array on the heap as part of the odp initialisation
...
odp foo;
foo.f = i;
foo.pstr = new wchar_t [1];
foo.pstr[0] = base[i];
vec.push_back(foo);
...
better still use std::wstring since you are using c++, and let it do the memory allocation and management for you.
It looks like pstr is pointing to the locally scoped variable loopStr, so the results are undefined (it appears to still have the last stored value in it when printing the results). If you printed the address of pstr in the loop, I believe it would be the same for each position in the loop.
foo.pstr = loopStr; // wchar_t* = wchar_t ? Why does this work?
This doesn't work, at least not in the way you want it to. loopStr is an array, but you can use it like a pointer too. So when you assign to the pointer foo.pstr, it gets the address of the first element in loopStr. That happens to be a local variable allocated on the stack and is only valid inside the for loop.