Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
Good day,
Please can someone assist? I am trying to reverse a member that is a pointer array.
string::string(char *c)
{
int i =0;
while ((c[i] != '\0'))
{
i++;
}
_lenght= i;
_aString=*&c;
}
void string::reverse() //Requirements specify to have this argument
{
for(int i=0; i<_lenght/2; i++)
{
std::swap(_aString[i], _aString[_lenght-i-1]);
}
}
I get a runtime error on this.
This is my main function
int main(){
string a;
std::cout << "a is " << a << "\n";
string b("12345");
string c("12345",3);
std::cout << "c is " << c << "\n";
c = a;
a = b;
std::cout << "a is " << a << "\n";
b.reverse();
std::cout << "a is " << a << "\n";
return 0;
}
Error I'm getting is
Unhandled exception at 0x00fd6710 in UnisaLesson1.exe: 0xC0000005: Access violation writing location 0x00fdfd08.
Sorry, I'm still a newb.
The problem is
_aString=*&c;
which is a weird way of writing
_aString=c;
so that _aString is simply pointing to whatever the function argument was; this class doesn't manage a the memory for a string (as std::string does), but refers to an external string managed elsewhere.
In your test case, that string is a string literal - which isn't modifiable. So attempting to modify it, as reverse does, gives undefined behaviour; if you're lucky, an access violation; if you're unlucky, data corruption or some other unwanted runtime behaviour.
If your class is supposed to manage the memory, then it will need to allocate it in the constructor. Assuming this assignment is an exercise in memory management (otherwise, just use std::string), you'd want something like
_aString = new char[_lenght];
std::copy(c, c+_lenght, _aString);
and don't forget the Rule of Three:
a destructor to release the memory with delete [] _aString
copy constructor, either deleted to prevent copying, or implemented to allocate a new buffer;
copy-assignment operator, either deleted to prevent copying, or implemented to copy into the existing buffer after resizing if necessary.
You might also consider fixing the spelling of _lenght to _length.
Related
This question already has answers here:
Undefined, unspecified and implementation-defined behavior
(9 answers)
Closed 6 years ago.
I was solving an online exercise related to de-allocating memory pointed to by pointer using delete keyword in C++. Following is my code.
#include<iostream>
#include<string>
#include<conio.h>
int main()
{
double *ptrDouble = new double;
*ptrDouble = 22;
std::cout << "\nValue of ptrDouble = " << *ptrDouble << std::endl;
delete ptrDouble;
std::cout << "Value of ptrDouble = " << *ptrDouble << std::endl;
getch();
}
So according to the online site where i am solving this exercise,
If you use the delete keyword on the pointer , the memory will be
deallocated and therefore the contents will not be available to your
application any longer. Attempting to access the contents will cause
your application to crash due to a memory violation.
But when i try to print the value of the ptrDouble after deallocating the memory, the program doesn't crashes, instead a garbage value is printed on the console.
Question is, am i doing something wrong or that online site is wrong about whether program should crash or not ?
PS. I am using visual studio 2015 community.
Accessing freed memory leads to undefined behavior. Crashing or reading garbage both fall into that category. Whether or not the program will actually crash depends on whether that particular block of memory was returned to the OS or merely made available for reuse.
This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 8 years ago.
Please consider this simple example:
#include <iostream>
const int CALLS_N = 3;
int * hackPointer;
void test()
{
static int callCounter = 0;
int local = callCounter++;
hackPointer = &local;
}
int main()
{
for(int i = 0; i < CALLS_N; i++)
{
test();
std::cout << *hackPointer << "(" << hackPointer << ")";
std::cout << *hackPointer << "(" << hackPointer << ")";
std::cout << std::endl;
}
}
The output (VS2010, MinGW without optimization) has the same structure:
0(X) Y(X)
1(X) Y(X)
2(X) Y(X)
...
[CALLS_N](X) Y(X)
where X - some address in memory, Y - some rubbish number.
What is done here is the case of undefined behaviour. However I want to understand why there is such behaviour in current conditions (and it is rather stable for two compilers).
It seems that after test() call first read of hackPointer leads to valid memory, but second successive instant read of it leads to rubbish. Also on any call address of local is the same. I always thought that memory for stack variable is allocated on every function call and is released after return but I can't explain output of the program from this point of view.
"Releasing" automatic storage doesn't make the memory go away, or change the pattern of bits stored there. It just makes it available for reuse, and causes undefined behaviour if you try to access the object that used to be there.
Immediately after returning from the function, the memory occupied by the local probably hasn't been overwritten, so reading it will probably give the value that was assigned within the function.
After calling another function (in this case, operator<<()), the memory is likely to have been reused for a variable within that function, so probably has a different value.
You are quite right that this is undefined behaviour.
That aside, what's happening is that std::cout << *hackPointer involves a function call: operator<<() gets called after the value of *hackPointer has been read. In all likelihood, operator<<() uses its own local variables that end up on the stack where local was, wiping out the latter.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
When trying to reduce memory use as much as possible, I have seen some programs use additional local scopes. Is this the best way to reduce footprint? Will the variables be removed from the stack when the brackets close? Would it be better to explicitly delete the objects, or is this equally good? Or would the compiler simply remove extraneous brackets?
void foo()
{
{
int a = 4;
BigObject obj1;
obj1.operations(a);
}
{
double b = 9;
BigObject obj2;
obj2.operations(b);
}
}
Yes, they introduce new scopes. Objects with automatic storage duration, i.e. objects on the stack ("local variables"), will go out of scope at the end of this scope.
You are guaranteed that destructors are called, but you are not guaranteed that the object is actually removed from the stack (since stack is an implementation detail -- the standard only talks about automatic storage duration).
However, there is rarely a performance reason for doing so. Instead, it can be useful when using the RAII pattern.
Note, however, that this only applies to local variables. Dynamically allocated memory, i.e. objects on the heap (that you allocate with new), will not be released until you explicitly delete them.
Dynamically allocated memory will have to be pointed to by pointers. C++ clearly separates the concepts of pointer to BigObject and BigObject. In other words, your program is ill-formed. You should write:
BigObject* obj1 = new BigObject();
// ^-- Important!
You can not delete variables with automatic storage, so that part of your question does not make sense.
Not that instead of using new, you should generally prefer using std::unique_ptr instead:
std::unique_ptr<BigObject> obj1 = make_unique<BigObject>();
The memory allocated for your BigObject will be automatically released when obj1 goes out of scope -- this is the RAII pattern.
I have pondered this in the past, but the reality is it does not actually save space according to my nasty experiment. The locals appear to still stock consecutively on the stack:
int _tmain(int argc, _TCHAR* argv[])
{
int* nasty = NULL;
{
int value = 1;
std::cout << &value << std::endl;
}
{
int value2 = 2;
std::cout << &value2 << std::endl;
}
{
int value3 = 3;
std::cout << &value3 << std::endl;
nasty = &value3;
}
std::cout << nasty[0] << ", " << nasty[3] << ", " << nasty[6] << std::endl;
return 0;
}
Output:
001FFC38
001FFC2C
001FFC20
3, 2, 1
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Modifying a const through a non-const pointer
I'm studying C++, and very interesting about pointers. And I tried to change value of a constant value (my teacher called it backdoor, please clarify if I'm wrong) like this:
const int i = 0;
const int* pi = &i;
int hackingAddress = (int)pi;
int *hackingPointer = (int*)pi;
*hackingPointer = 1;
cout << "Address:\t" << &i << "\t" << hackingPointer << endl;
cout << "Value: \t" << i << "\t\t" << *hackingPointer << endl;
system("PAUSE");
return 0;
However, the result is very strange. Although the two addresses are the same, the values are different.
How is my code executed? And where is 0 and 1 value is stored exactly?
You've discovered a little thing that C++ developers call undefined behavior. You told the compiler that "i is a constant with the value 0". So when you ask the compiler for the value of i, it tells you that it is 0.
Mucking around with trying to change the value of a constant violates the assumptions made by the compiler (that constants are going to be, well, constant), and so, the compiler is going to generate invalid or inconsistent code.
There are a lot of situations in C++ where it is possible to do something without the compiler catching it as an error, but the result is undefined. And if you do that, then you get results like what you're seeing. The compiler does something weird and unexpected.
Oh, and if your teacher is trying to teach you anything from an example such as this, he's wrong, and you should be very scared.
The only guarantee you get from code like this is this:
the compiler can do literally anything it likes
When you write code, you have an implicit contract with the compiler:
"If I write well-defined C++ code, then you convert it into an executable with the same effects as described by the C++ standard".
When you do something like this, you violate the contract. And then the compiler isn't obliged to follow it either. If you give the compiler code that is not well-defined according to the C++ standard, then it can't, and isn't going to, create an executable which does as the C++ standard specifies.
It seems, that compiler has optimized (inlined int const value)
cout << "Value: \t" << i << "\t\t" << *hackingPointer << endl;
to
cout << "Value: \t" << 0 << "\t\t" << *(0x0044ff28) << endl;
Anyway, you have still succeeded to change value of memory where i is stored. But do not try this at home :-)
It is not permitted to change the values of a constant, in fact it's undefined behaviour so your program could do anything as a result.
In this instance it looks like your compiler optimised the read away at compile time because it knew the value is fixed. Lots of implementations might just crash when you try and change it, but you cannot and should not bet or rely upon the result of any undefined behaviour ever.
Hii
I know that vector allocated contiguous fixed memory when it needs to push_back some items.And if its not able to fit into it it will alllocate new memory and copy old values into it and delete the old memory.
If that is the case how the following code works
#include<iostream>
#include<vector>
using namespace std;
class Test
{
public :
int val;
Test()
{
val=0;
}
};
int main()
{
vector<Test>vec;
Test t[10];
for (int i=0;i<5;i++)
vec.push_back(t[i]);
cout<<vec.capacity()<<endl; //printing 8
Test* obj=&vec[2];
obj->val=2;
cout<<obj<<endl;
for (int i=0;i<5;i++) //Adding 5 elements more
vec.push_back(t[i]);
Test* obk=&vec[2];
cout<<obk->val<<endl;
cout<<obj->val<<endl;
cout<<obj<<endl;
cout<<obk<<endl;
}
Here if you see obj is taking pointer of vec[2] which value in my machine is coming 0x8bcb048 .Then I am inserting 5 more items so vector will allocate new memory.Now if i am taking obk from vector[2] its coming different address 0x8bcb070 . But if i try to acess i with the help of obj its not giving any problem.Any reason ?
But if i try to access it with the help of obj its not giving any problem. Any reason?
This is undefined behavior - the fact that it appears to work is simply due to luck (whether good or bad luck is matter of opinion).
Essentially you're dereferencing a 'dangling' pointer. and just like if you dereference a pointer to a block of memory that's been freed, you simply read out old, stale data that happens to look like it has reasonable values. or you might read out something that appears to be garbage. Or you might cause a segfault.
One thing is for certain - it's a bug, whether it seems to act like one or not.
vectors are dynamic arrays. You are right when they overflow they are reallocated someplace else and all earlier initialized pointers/ iterators( which generally for vectors are also implemented as pointers, although the standards don't require it)/ address references become invalid. and earlier held memory space is freed finally.
Here is how events occur in simplistic terms:
currently available space is insufficient.
new memory space is acquired ( k times(generally k=2) as large as original memory size)
current array is copied to new memory locations
old = current; current = new; { this ensures atomicity for single insertions}
old memory is freed.
Notice that old memory location's data is not destroyed or reset. So when the resources are needed again that might or might not be reused. But the original memory location that you have is a false location and must be avoid always.
When a vector reallocates, all iterators, pointers and references that you obtained prior to the reallocation are invalidated. Using them leads to undefined behavior, which includes "apparently not giving any problems".
To visualize the problem, you can insert debug outputs in the constructors and the destructor. You could also log which objects exist at any point in time:
class Test;
std::set<Test*> valid_Test_objects;
class Test
{
int val;
public:
Test() : val(0)
{
valid_Test_objects.insert(this);
std::cout << "constructed Test object # " << this << std::endl;
}
Test(const Test& that) : val(that.val)
{
std::cout << "constructed Test object # " << this << std::endl;
valid_Test_objects.insert(this);
}
~Test()
{
std::cout << "destructing Test object # " << this << std::endl;
valid_Test_objects.erase(this);
}
int value()
{
std::cout << " accessing Test object # " << this << std::endl;
if (valid_Test_objects.find(this) == valid_Test_objects.end())
{
abort();
}
return val;
}
};
int main()
{
std::vector<Test> vec;
vec.reserve(3);
Test x;
vec.push_back(x);
Test* p = &vec[0];
std::cout << p->value() << std::endl;
std::vector<Test>::size_type cap = vec.capacity();
while (cap == vec.capacity()) vec.push_back(x);
std::cout << p->value() << std::endl;
}
Unfortunately, we should not even try to call p->value() when p is invalid. Enjoy your stay at undefined behavior land ;-)
If you're asking why there's no crash when you try to access 'obj' then I would say you should try to run it in Release mode and see. In any case, obj should not be accessible, as the pointer that was returned by &vec[2] was invalidated when the vector increased its capacity. It could still be pointing to some random junk that happens to be allocated to your processes.