I have a struct like these:
struct Node {
void *data;
Node *l, *r;
}
And I should use function:
void push(Queue *q, void *data, int priority) {
Node *n = new Node;
n->data = data;
// place node in queue
}
I'm trying to read strings in loop, but after that I got queue where all values in nodes are similar.
void read_input(Queue *q) {
string s;
int p;
cin >> s >> p;
// problem is here
push(q, (void *) s.c_str(), p);
}
void main() {
Queue *q = create();
for (int i = 0; i < 5; i++) {
read_input(q);
}
}
How can I fix that? Why string s always has the same address?
Like Trantor said, you using s.c_str() which is a private pointer of string s; and is valid only inside read_input function.
Every call to read_input will use this pointer that is destroyed every time you reach read_input end (out of scope).
You see the same pointer, probably because its on the stack. Its a coincidence.
To fix your issue, you need to create a copy of the characters and store them in node->data. However you will also need to think where to delete it. E.g. OnNodeDestroy event or similar.
The problem is, you are saving (temporary) pointers to the private internals of temporary objects of class std::string in your queue push call. They become invalid after leaving read_input, and may be even reused internally, so the pointer seems not to change.
Instead you should work with copies, allocate your own memory for the strings.
When you have created a string object compiler will allocate the memory from stack and all the time that string object will pointing to that particular memory location (static memory allocation in this case) only. In your structure void *data pointer will also always pointing to that same memory location. Hence the last value entered into string object will reflect in all the node in your stack. To fix this you have to dynamically allocate memory each time so that the data pointer should pointing to different memory location and you will get different value.
void read_input(Queue *q) {
//string s;
char *s = (char *)malloc(50);
int p;
cin >> s >> p;
push(q, (void *) s, p);
}
Related
Hello stackoverflow
so my question is: I want to make a function to generate the array of structures but i get an error whenever i finish inserting the values what is the problem?
like so
struct INFO
{
char name[20]; // creating the strucure
int age;
};
void generateArr(INFO *p); // a function to generate the array
void readArr(INFO *p); // a function to read the array
int main()
{
INFO *ptr =new INFO; // a pointer that points to the structure
generateArr(ptr); // calling the functions
readArr(ptr);
delete[]ptr; // deallocating memory
}
void generateArr(INFO *p)
{
p = new INFO [3]; // generating three INFO structures
}
void readArr(INFO *p)
{
for (int i = 0; i < 3; i++)
{
cin >> p[i].name>> p[i].age; // inputting the elements
cout << endl;
}
}
I tried to make the code as clear as possible, ask me if anything is ambiguous.
This function :
void generateArr(INFO *p)
{
p = new INFO [3]; // generating three INFO structures
}
is not working as you expect it does. It assigns allocated memory to local 'p` parameter, which is not returned to a main. To fix it change p to reference:
void generateArr(INFO *&p)
[edit]
but since you already assigned ptr in main with INFO *ptr =new INFO;, you will get a memory leak this way. So you should remove that line.
In generateArr(INFO *p), you allocate an array which address is stored in local variable p; on return from the function, any local variable (such as p) is lost, as long as address of the allocated array.
You should get rid of function generateArr(INFO *p), which is useless, and allocate your array into main(), this way :
int main()
{
INFO *ptr =new INFO[3];
readArr(ptr);
delete[]ptr; // deallocating memory
}
Rewrite the functions at least the following way
INFO * generateArr( size_t n )
{
return new INFO [n]; // generating three INFO structures
}
void readArr(INFO *p, size_t n )
{
for (int i = 0; i < n; i++)
{
cin >> p[i].name>> p[i].age; // inputting the elements
cout << endl;
}
}
and in main call them like
const size_t N = 3;
INFO *ptr = generateArr( N ); // a pointer that points to the structure
readArr( ptr, N );
delete []ptr; // deallocating memory
As for your code then in this statement
INFO *ptr =new INFO; // a pointer that points to the structure
there is allocated only one object of the structure type however it is deleted using operator delete [] instead of the operator delete.
delete[]ptr; // deallocating memory
And inside this function
void generateArr(INFO *p)
{
p = new INFO [3]; // generating three INFO structures
}
there is a memory leak because variable p is a local variable of the function that was initialized by the value of the function's argument and that will be destroyed after exiting the function. As result the address of the dynamically allocated memory will be lost.
I'm implementing a simple trie data structure in c++ using struct and pointers. When I pass a string to add in trie, it gives segmentation fault in the addString() function.
struct node {
char ch;
node *link[26];
node() : link(){}
};
node head;
void addString(node *n, string s) {
if (!s.length()) return;
if (!n -> link[(int)s[0] - 97]) {
node m;
m.ch = s[0];
n -> link[(int)s[0] - 97] = &m;
}
addString(n -> link[(int)s[0] - 97], s.substr(1));
}
int main(){
addString(&head, "red");
return 0;
}
I tried debug statements and even printed and matched the address values of newly created node and the one passed recursively, they were same.
PS I'm using head node as epsilon state.
You are using addresses of objects allocated on stack. node m; is on stack. It will be deleted as soon as you leave an if block in which it is declared. And you assign it's address to a node n -> link[(int)s[0] - 97] = &m; which lives longer than that.
n -> link[(int)s[0] - 97] = &m;
You're storing the address of m while it is destroyed at the end of its scope.
You should redesign your project with a proper memory management.
There are two problems that could explain segmentation fault:
the first is that you add a pointer to a local object m into your array of links. As soon as you return from the function the pointer will be dangling and you'll have UB. Allocate m properly: node *m = new node; Better: use unique_ptr instead of raw pointers.
you assume that the string contains only lower case letters between 'a' and 'z'. If the string would contain anything else, you'll go out of bounds and might cause memory corruption and UB. You should have at least an assert()
Here a small fix to address both issues, based on your current structure and approach:
struct node {
...
node(char c=0) : link(), ch(c) {}
~node() { for (int i=0;i<26; i++) delete link[i]; }
};
...
void addString(node *n, string s) {
if (!s.length()) return;
size_t c = tolower(s[0]);
if (c<'a' || c>'z') return; // char not ok-> do like end of string
if (!n -> link[c-'a']) {
n -> link[c-'a'] = new node(c);
}
addString(n -> link[c-'a'], s.substr(1));
}
Note that when you use pointers in a struct, you have to be extra-careful about the rule of 3. It will not hurt here, though, as you do'nt copy nodes yet.
Online demo
I am using this simple function to create a new node
node* Tree::createNewNode(int score, const char* word)
{
// Create a new node with the information available
node* n = new node;
n->left=NULL;
n->right = NULL;
n->parent = NULL;
n->score = score;
strcpy(n->word,word);
return n;
}
node is a structure:
struct node
{
int score; // the score or label of the node
char *word; // the word stored in the node
node *left; // the pointer to left child of the node
node *right; // the pointer to right child of the node
node *parent; // the pointer to parent node
};
And I am calling the createNewNode function from another function
temp = t->createNewNode(score,"");
The function runs properly for only one time and then it crashes while executing:
node* n = new node;
You need to allocate memory to the word field. You are trying to copy data into word with out allocating space for it.
change char *word to char word[100];
char *word; // this is a pointer to string, aka this is not a string
char word[100]; // this is a string
n->word is uninitialized. when you are using strcpy you are copying word content in an unknown address.
This result on unknown behavior (The first call look like it work and the second made the program crash). You need to allocate the memory space to hold word string inside the structure.
Your error is due to word not being allocated memory.
You could fix this using legacy C functionality like in the other answers, or you could actually write idomatic C++.
All of the initialization done in the createNewNode function should be done in the node constructor. You should use std::string instead of char* to avoid memory allocation failures like you currently have. You should also protect the members of your node class, instead providing mutators to attach/detach them from the tree so you don't need to do it manually.
Your program crashes in the following line,
strcpy(n->word,word);
because, n->word in struct node
char *word; // the word stored in the node
was not allocated any memory.
Use char array instead of char pointer or change the function definition like this:
node* createNewNode(int score, const char* word, int wordLen)
{ ^^^^
// Create a new node with the information available
node* n = new node;
n->left=NULL;
n->right = NULL;
n->parent = NULL;
n->score = score;
n->word = (char *) malloc(wordLen);
strcpy(n->word,word);
return n;
}
strcpy(n->word, word) copies the input string into n->word which has not been initialized. For that experession to work correcly n->word must point to an allocated buffer.
strdup function allocates that buffer for you and copies the input string into that buffer, e.g.:
n->word = strdup(word);
I have a class String with the following members:
Class String{
...
private:
char* word
int length
}
String's copy assignment returns a String& and allocates word on the heap.
I also have a linked list class written in C that has a function:
void *popFront(struct List *list)
{
struct Node prevHead = list->head
list->head = prevHead->next;
void *info = prevHead->info;
free(prevHead);
return info;
}
My task is to write the same function for a C++ linked list that uses the C function. This is what I have:
String List::popFront()
{
String s = (*(String *) ::popFront(&list));//casting the void * to String
return s;
}
The C++ method should return the object by value. That's what I thought the method would do. However,
I'm getting memory leaks. Any hint on how I need to modify List::popFront() so that it returns by value? Thanks.
First store the returned pointer locally as a pointer to string, then make a local copy of the string, then delete the object, the pointer points to and finally return the local copy.
EDIT:
Btw. you can use c++11's smart pointers to avoid the extra copy:
String List::popFront()
{
auto s = std::unique_ptr<String>((String*) ::popFront(&list));
return *s;
}
but that is probably not, what your teacher aims at.
popFront removes the element from the linked list and frees the node, but not the info portion. This is the responsibility of the caller of popFront, e.g.
String *s = (String *) ::popFront(&list);
delete s;
But you must also keep a copy, which you can return from the method
String List::popFront()
{
String *s = (String *) ::popFront(&list);
String tmp = *s;
delete s;
return tmp;
}
You declare String List::popFront() which returns an object, not a pointer. And String s = ... declares an object, not a pointer or reference. So assigning s a value constructs a new object s being a copy of what ::popFront returned, then a next copy of s is returned and s itself gets destroyed. However the object unlinked by ::popFront() remains on a heap, making a leak.
Don't create an intermediate copy of String object, return the pointer to unlinked object, so that a caller can link it to its own list or delete it after use:
String *List::popFront()
{
String *s = (String *) ::popFront(&list);//casting the void * to String *
return s;
}
vector<ClassX> xVec;
if (inputFile.peek() == '$')
{
classX classXInstance; //<==================== local instantiation
readFileElements(classXInstance);//<== pass by reference
if(classXInstance.validate())
{
xVec.push_back(classXInstance);///<=============== added here
}
/// destructor of the local copy is called here
}
I get a core dump, tried to debug, however I get so much junk messages with gdb, all I can see that the vector got corrupted, NOT sure if it because the destructor is called is a reason??
EDIT:
my class look like this
class ClassX
{
public:
ClassX() { numberOfX=0; ppXX = NULL; };
~ClassX();
void validate();
char **setX(const vector<string>& Xss);
inline char **getX() {return ppXX;};
private:
int numberOfX;
char **ppXX;
};
and it contains a destructor as follow
ClassX::~ClassX()
{
if (ppXX != NULL)
{
for(int i=0; i < numberOfXX; i++)
{
if (ppXX[i] != NULL)
{
delete [] ppXX[i];
ppXX[i] = NULL;
}
}
// Free array of pointers.
delete [] ppXX;
ppXX = NULL;
}
}
the setX allocate all memory necessary
validate give me a printout of the ppXX[i] and return true if number of elements matches the size of string vector
A copy of classXinstance is stored into xVec, with a pointer ppXX to a region in memory. Now you have two objects pointing to the same region. A moment later, classXinstance is destroyed, so the region is subject to delete. The element within xVec is now pointing to invalid memory.
The best option is to use std::Vector<std::string> instead of char **ppXX; a vector of strings takes care of references and allocation so you don't need to worry about proper construction/copy/destruction.