strcpy works fine, even though memory is not allocated - c++

Below c++ program works fine, even though i have not allocated any memory to chr.
I went through google, SO and came across this
Why does this intentionally incorrect use of strcpy not fail horribly?
Here the program works fine for destination which has space less than the source.
Does that apply in my case also,strcpy writes into a random location in the heap?
#include<iostream>
using namespace std;
class Mystring
{
char *chr;
int a;
public:
Mystring(){}
Mystring(char *str,int i);
void Display();
};
Mystring::Mystring(char *str, int i)
{
strcpy(chr,str);
a = i;
}
void Mystring::Display()
{
cout<<chr<<endl;
cout<<a<<endl;
}
int main()
{
Mystring a("Hello world",10);
a.Display();
return 0;
}
output:-
Hello world
10
I tried the same thing with another c++ program, with any class and class member, and i was able to see the crash.
#include<iostream>
using namespace std;
int main()
{
char *src = "Hello world";
char *dst;
strcpy(dst,src);
cout<<dst<<endl;
return 0;
}
Please help me understand the behavior in the first c++ program.Is memory allocated somehow or strcpy is writing to some random memory location.

The behavior of your program is undefined by the C++ standard.
This means that any C++ implementation (e.g. a compiler) can do whatever it wants. Printing "hello!" on stdout would be a possible outcome. Formatting the hard disk would still be acceptable, as far as the C++ standard is involved. Practically, though, some random memory on the heap will be overwritten, with unpredictable consequences.
Note that the program is even allowed to behave as expected. For now. Unless it's Friday. Or until you modify something completely unrelated. This is what happened in your case, and is one of the worst thing to happen from the point of view of a programmer.
Later on, you may add some code and see your program crash horribly, and think the problem lies in the code you just added. This can cause you to spend a long time debugging the wrong part of the code. If that ever happens, welcome to hell.
Because of this, you should never, ever, rely on undefined behavior.

strcpy() is indeed writing to a random location.
And it's a blind luck if your program runs fine and nothing crashes.
You have created on object of MyString class on a stack. In that object there's a member pointer chr, which points to some arbitrary location. Does your constructor take care to initialize that pointer or allocate a memory for the pointer to point at? -- No, it doesn't. So chr points somewhere.
strcpy() in its turn doesn't care about any pointer validity, it trusts your professionalism to provide valid input. So it does its job copying stings. Luckily, overwriting memory at the location pointed by an uninitialized chr doesn't crash you program, but that's "luckily" only.

It is known that strcpy() can cause overflow errors, because there is no check made wherever the data will fit in the new array or not.
The outcome of this overflow may sometime never been noticed, it all depends on where the data is written. However a common outcome is heap and/or program corruption.
A safe alternative of strcpy() is the usage of strcpy_s() that requires also the size of the array. You can read more about the usage of strcpy_s() on MSDN or here

Actually, strcpy() does something like this:
char *strcpy(char *dest, const char *src)
{
unsigned i;
for (i=0; src[i] != '\0'; ++i)
dest[i] = src[i];
dest[i] = '\0';
return dest;
}
So, when you pass a pointer to some character array to strcpy, it copies data from src to dest until it reaches NULL terminated character.
Character pointer does not contain any information about length of string, so when you pass dest pointer, it copies data even though you haven't assigned memory to it.
Run this example code, you will get my point:
#include <cstring>
#include <iostream>
using namespace std;
int main()
{
char str1[] = "Hello_World!";
char str2[5];
char str3[10];
strcpy(str2,str1);
cout << "string 1:" << str1 << endl;
cout << "string 2:" << str2 << endl;
cout << "string 3:" << str3 << endl;
return 0;
}
This will not show any error but you can understand by my example that this is not a good practice.

Related

_alloca and std::vector of const char*

I did several searches on the _alloca function and it is generally not recommended.
I will have a dynamically updated array of strings on which I will have to iterate often.
I would like to have each string allocated on the stack to reduce the miss caches as much as possible.
Using _alloca I could create a char* on the stack and put it in the vector.
My char will be in a vector which will not impact my stack and I know that the strings will never be big enough to make a stackoverflow when I allocate them on the stack.
Is it a bad thing to use it in this case?
Does the program do what I want it to do?
#include <vector>
#include <cstring>
#ifdef __GNUC__
# define _alloca(size) __builtin_alloca (size)
#endif /* GCC. */
std::vector<const char*> vec;
void add(const char* message, int size) {
char* c = (char*) _alloca (size * sizeof(char*));
std::memcpy(c, message, sizeof(message));
vec.push_back(c);
}
int main() {
const char* c = "OK";
for (int i = 0; i < 10; ++i) {
add(c, 2);
}
}
Stack memory allocated by _alloca gets automatically released when the function that calls _alloca returns. The fact that a pointer to it gets shoved someplace (specifically some vector) does not prevent this memory from being released (as you mentioned you assumed would happen, in the comments), that's not how C++ works. There is no "garbage collection" in C++.
Therefore, the shown code ends up storing a pointer to released stack memory. Once add() returns, this leaves a dangling pointer behind, and any subsequent use of it results in undefined behavior.
In other words: yes, it's "a bad thing to use it in this case", because be the shown code will not work.
There are also several other, major, issues with this specific _alloca call, but that's going to be besides the point. This entire approach fails, even if these issues get fixed correctly.

How variable 'a' will exist without any object creation?

How variable int a is in existence without object creation? It is not of static type also.
#include <iostream>
using namespace std;
class Data
{
public:
int a;
void print() { cout << "a is " << a << endl; }
};
int main()
{
Data *cp;
int Data::*ptr = &Data::a;
cp->*ptr = 5;
cp->print();
}
Your code shows some undefined behavior, let's go through it:
Data *cp;
Creates a pointer on the stack, though, does not initialize it. On it's own not a problem, though, it should be initialized at some point. Right now, it can contain 0x0badc0de for all we know.
int Data::*ptr=&Data::a;
Nothing wrong with this, it simply creates a pointer to a member.
cp->*ptr=5;
Very dangerous code, you are now using cp without it being initialized. In the best case, this crashes your program. You are now assigning 5 to the memory pointed to by cp. As this was not initialized, you are writing somewhere in the memory space. This can include in the best case: memory you don't own, memory without write access. In both cases, your program can crash. In the worst case, this actually writes to memory that you do own, resulting in corruption of data.
cp->print();
Less dangerous, still undefined, so will read the memory. If you reach this statement, the memory is most likely allocated to your program and this will print 5.
It becomes worse
This program might actually just work, you might be able to execute it because your compiler has optimized it. It noticed you did a write, followed by a read, after which the memory is ignored. So, it could actually optimize your program to: cout << "a is "<< 5 <<endl;, which is totally defined.
So if this actually, for some unknown reason, would work, you have a bug in your program which in time will corrupt or crash your program.
Please write the following instead:
int main()
{
int stackStorage = 0;
Data *cp = &stackStorage;
int Data::*ptr=&Data::a;
cp->*ptr=5;
cp->print();
}
I'd like to add a bit more on the types used in this example.
int Data::*ptr=&Data::a;
For me, ptr is a pointer to int member of Data. Data::a is not an instance, so the address operator returns the offset of a in Data, typically 0.
cp->*ptr=5;
This dereferences cp, a pointer to Data, and applies the offset stored in ptr, namely 0, i.e., a;
So the two lines
int Data::*ptr=&Data::a;
cp->*ptr=5;
are just an obfuscated way of writing
cp->a = 5;

C++ Cout crashes when using pointer

I am pretty new to C++, and while getting started I got stuck on a frustrating problem concerning pointers. Consider the following code:
#include <iostream>
using namespace std;
int main (){
int* mypointer;
*mypointer = 1;
cout << "Whats wrong";
}
It crashes during runtime. I suspect it has to do with the pointer assignment. But after commenting out the cout statement, the program executes. By assigning the pointer as
int* mypointer, myvar;
myvar = 1;
mypointer = &myvar;
the program runs, and I can print the value of the pointer as:
cout << "value of pointer: " << *mypointer;
I draw the conclusion that this would be the correct usage of a pointer.
BUT: Why does the following code execute??:
#include <iostream>
#include <stdio.h>
using namespace std;
int main (){
int* mypointer;
*mypointer = 1;
printf("This works!\n");
printf("I can even print the value mypointer is pointing to: %i",*mypointer);
}
Simply using printf?? I would really appreciate an explanation guys!
The code executes because, just by chance, your compiler has managed to optimise the program down enough that the 1 is "hardcoded" into the printf call.
It would probably have done this anyway, rendering both the original int and the pointer irrelevant, but in this instance it's not reflecting the fact that the pointer was broken and there wasn't an original int.
so, strictly speaking, this doesn't even reflect the semantics of the program: as you've spotted, assigning a value to an int that doesn't exist (through an uninitialised or otherwise invalid pointer) is nonsense and results in undefined behaviour.
But that's the nature of undefined behaviour: anything can happen! The authors of your compiler are making the most of that, by realising that they don't have to write any code to make this case work logically. Because it's you who violated the C++ contract. :)

doubts in this program about classes- constructors and destructors

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.

string::c_str query

Where does the pointer returned by calling string::c_str() point to ? In the following code snippet, I thought I will give get a segmentation fault but it gives me the correct output. If the pointer returned by string::c_str() points to an internal location inside the string object, then when the function returns and the object destructor gets invoked, I should get an invalid memory access.
#include <iostream>
#include <string>
using namespace std;
const char* func()
{
string str("test");
return str.c_str();
}
int main()
{
const char* p = func();
cout << p << endl;
return 0;
}
Output: test
Compiler: g++ 4.3.3
Platform: ubuntu 2.6.28-19
Where does the pointer returned by calling string::c_str() point to?
It points to some place in memory where a null-terminated string containing the contents of the std::string is located.
The pointer is only valid until the std::string is modified or destroyed. It is also potentially invalidated if you call c_str() or data() again.
Basically, your safest bet is to assume the pointer obtained from c_str() is invalidated the next time you do something to the std::string object.
I should get an invalid memory access.
No, you get undefined behavior. You might get a memory access error of some kind (like a segmentation fault), but your program also might appear to continue running correctly. It might appear to work one time you run your program but fail the next.
What would you expect this to print out?
#include <iostream>
#include <string>
int main()
{
int* test = new int[20];
test[15] = 5;
std::cout << test[15] << "\n";
delete[] test;
std::cout << test[15] << "\n";
return 0;
}
In release mode on VS 2010, I get this result:
5
5
Deallocated memory doesn't necessarily throw an exception when you try to access it. The value doesn't necessarily get re-written, either. (Interestingly enough, if I change the compile to debug mode, the compiler overwrites the value with -572662307).
What happens when you try to access it is undefined by the standard. That means the compiler can do whatever it feels like doing, or choose to do nothing. (Or crash your program, or blow up the universe...)