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.
Related
I need to use an array of strings with an unknown size. Here I have an example to see if all works fine. I need to know that array's size in ClassC but without passing that value as an argument. I've see so many ways to do it (here and in google) but as you will see now, they didn't work. They return the number of chars in the first position of the array.
void ClassB::SetValue()
{
std::string *str;
str = new std::string[2]; // I set 2 to do this example, lately it will be a value from another place
str[0] ="hello" ;
str[1] = "how are you";
var->setStr(str);
}
Now, in ClassC if I debug, strdesc[0] ="hello" and strdesc[1] = "how are you", so I suppose that class C is getting the info ok....
void classC::setStr(const std::string strdesc[])
{
int a = strdesc->size(); // Returns 5
int c = sizeof(strdesc)/sizeof(strdesc[0]); // Returns 1 because each sizeof returns 5
int b=strdesc[0].size(); // returns 5
std::wstring *descriptions = new std::wstring[?];
}
So.. in classC, how can I know strdesc's array size, that should return 2?? I have also tried with:
int i = 0;
while(!strdesc[i].empty()) ++i;
but after i=2 the program crashes with a segmentation fault.
Thanks,
Edit with the possibles SOLUTIONS:
Conclusion: There is no way to know the array's size once I pass its pointer to another function
Pass the size to that function... or...
Use vectors with std::vector class.
how can I know strdesc's array size
You cannot know the size of an array from a pointer to that array.
What you can do is pass the size as another parameter. Or even better, use a vector instead.
but after i=2 the program crashes with a segmentation fault.
Accessing beyond the array boundary has undefined behaviour.
With this Kind of code you will get memory leaks and other kind of C-style problems.
use vector:
#include <vector>
#include <string>
#include <iostream>
...
std::vector<std::string> my_strings;
my_strings.push_back("Hello");
my_strings.push_back("World");
std::cout << "I got "<< my_strings.size() << " strings." << std::endl;
for (auto& c : my_strings)
std::cout << c << std::endl;
I'm looking for a way to associate a char array with a string so that whenever the char array changes, the string also changes. I tried to put both char array and string variables in a union but that didn't worked as the compiler complained...
Any ideas are welcome...
class Observable_CharArray
{
char* arr;
std::function<void(char*)> change_callback;
public:
Observable_CharArray(int size, std::function<void(char*)> callback)
: arr(new char[size]), change_callback(callback){}
~Observable_CharArray()/*as mentioned by Hulk*/
{
delete[] arr;
}
void SetCallback(std::function<void(char*)> callback)
{
change_callback = callback;
}
/*other member function to give access to array*/
void change_function()
{
//change the array here
change_callback(arr);
}
};
class Observer_String
{
std::string rep;
void callback(char* cc)
{
rep = std::string(cc);
}
public:
Observer_String(Observable_CharArray* och)
{
och->SetCallback(std::bind(&callback, this, _1));
}
/*other member functions to access rep*/
};
The design can definitely be improved.
There can be other ways to solve your actual problem rather than observing char arrays.
The problem is that the std::string may change the string array inside (especially when it resizes). For instance, c_str returns the address of the current string - documentation says that "The pointer returned may be invalidated by further calls to other member functions that modify the object.".
If you're sure you won't call string methods (hence the string will stay at the same memory location), you could try accessing the c_str pointer (your char array) directly and modify its content.
std::string str = "test";
char* arr = (char*)str.c_str();
arr[3] = 'a';
NOTE: I strongly advice against this unless in a testing context.
In other words, the string class doesn't guarantee it's going to stay in the same place in memory - meaning trying to access it through a char array is impossible.
The best is to create another string class that enforces the char array to always stay the same size (and so can stay in the same memory position all the time). You could also create a bigger array (max size string for instance) to cope with any string size changes - but that should be enforced in your wrapper class.
Well you can do this, but you shouldn't
#include <iostream>
#include <string>
int main()
{
std::string test("123456789");
std::cout << test << "\n";
char* data = &test.front(); // use &(*test.begin()) for pre-C++11 code
for ( size_t i(0); i < test.size(); ++i )
{
data[i] = 57 - i;
}
std::cout << test << "\n";
}
Output will be
123456789
987654321
This however goes again everything std::string is trying to facilitate for you. If you use data, you risk causing UB and changes to test may make data point to garbage.
You should not do this!
However, there are many (dangerous) ways to achieve it:
char* cStr = const_cast<char*>(cppStr.c_str());
or
char* cStr = const_cast<char*>(cppStr.data());
or
char* cStr = &cppStr[0];
But beware that the cppStr might be reallocated whenever you touch it, hence invalidating your cStr. That would crash at some point in time, although maybe not immediately (which is even worse).
Therefore, if you are going to do this anyway. Make sure to cppStr.reserve(SOMETHING) *before* you get the cStr out of it. This way, you will at least stabilise the pointer for a while.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
C++ deprecated conversion from string constant to 'char*'
I want to pass a string via char* to a function.
char *Type = new char[10];
Type = "Access"; // ERROR
However I get this error:
error: deprecated conversion from string constant to 'char*'
How can I fix that?
If you really want to modify Type:
char *Type = new char[10];
strcpy( Type, "Access" );
If you don't want to modify access:
const char *Type = "Access";
Please note, that, however, arrays of char in C and in C++ come with a lot of problems. For example, you don't really know if the call to new has been successful, or whether it is going to throw an exception. Also, strcpy() could surpass the limit of 10 chars.
So you can consider, if you want to modify type later:
std::string Type = "Access";
And if you don't want to modify it:
const std::string Type = "Access";
... the benefit of using std::string is that it is able to cope with all these issues.
There are a couple of things going on here.
char *Type = new char[10];
This create a char* pointer named Type and initializes it to point to the first element of a newly allocated 10-element array.
Type = "Access"; // ERROR
This assignment doesn't do what you think it does. It doesn't copy the 6-character string "Access" (7 characters including the terminating '\0') to the array you just created. Instead, it assigns a pointer to the first element of that array into your pointer Type. There are two problems with that.
First, it clobbers the previous value of Type. That 10-character array you just allocated now has nothing pointing to it; you can no longer access it or even deallocate it. This is a memory leak.
This isn't what the compiler is complaining about.
Second, a string literal creates a statically allocated const array ("statically allocated" meaning it exists for the entire execution of your program). Type is not declared with a const qualifier. If the compiler allowed you to point Type to the string "Access", you could use that pointer to (attempt to) modify it:
Type = "Access";
Type[0] = 'a'; // try to change the string to "access"
The purpose of const is to prevent you from modifying, or even attempting to modify, things that are read-only. That's why you're not allowed to assign a non-const pointer value to a const pointer object.
Since you're programming in C++, you're probably better off using std::string.
I want to pass a string via char* to a function.
Here is how you can pass a string via char* to a function (note the required const keyword in the function signature.)
#include <iostream>
void f(const char* p) {
std::cout << p << "\n";
}
int main() {
f("Access");
}
But, what if you are invoking an existing function, and cannot modify its signature?
If you have some external guarantee that the function will not write through its argument pointer,
#include <iostream>
void f(char* p) {
std::cout << p << "\n";
}
int main() {
f(const_cast<char*>("Access"));
}
If, on the other hand, the function might write to the string, then you'll need to allocate space for the string:
#include <iostream>
void f(char* p) {
*++p;
std::cout << p << "\n";
}
int main() {
// Allocate read-write space on the heap
char *p = new char[strlen("Access"+1)];
// Copy string to allocated space
strcpy(p, "Access");
f(p);
delete p;
}
or,
#include <iostream>
void f(char* p) {
*++p;
std::cout << p << "\n";
}
int main() {
// Allocate read-write space on the stack
char arr[] = "Access";
f(arr);
}
But, the best course by far is to avoid the whole pointer mishegas:
#include <iostream>
void f(const std::string& p) {
std::cout << p << "\n";
}
int main() {
f("Access");
}
You've got a basic operations problem here, not a coding issue.
When you want to change the contents of a C char array, you do not use the assignment operator. That will instead change the value of the underlying pointer. Ick.
Instead you are supposed to use the C string library routines. For instance, strcpy (Type, "Access"); will copy the string literal "Access" into your character array, with its all-important trailing nul character.
If you are using C++ (as your tags indicate), you should probably be using std::string instead of arrays of char. Assignment works they way you are expecting there.
#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.
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.